GCC Code Coverage Report


Directory: ./
File: sql/sql_table.cc
Date: 2022-12-06 21:40:42
Exec Total Coverage
Lines: 6845 7613 89.9%
Branches: 8880 14073 63.1%

Line Branch Exec Source
1 /*
2 Copyright (c) 2000, 2022, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 /* drop and alter of tables */
26
27 #include "sql/sql_table.h"
28
29 #include <assert.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <stdint.h>
33 #include <stdio.h>
34 #include <string.h>
35
36 #include <algorithm>
37 #include <atomic>
38 #include <functional>
39 #include <memory>
40 #include <optional>
41 #include <string>
42 #include <string_view>
43 #include <type_traits>
44
45 /* HAVE_PSI_*_INTERFACE */
46 #include "my_psi_config.h" // IWYU pragma: keep
47
48 /* drop_table_share with WITH_LOCK_ORDER */
49 #include "mysql/psi/psi_table.h" // IWYU pragma: keep
50
51 /* PSI_TABLE_CALL() with WITH_LOCK_ORDER */
52 #include "mysql/psi/mysql_table.h" // IWYU pragma: keep
53
54 #include "decimal.h"
55 #include "field_types.h" // enum_field_types
56 #include "lex_string.h"
57 #include "libbinlogevents/include/binlog_event.h"
58 #include "m_ctype.h"
59 #include "m_string.h" // my_stpncpy
60 #include "map_helpers.h"
61 #include "mem_root_deque.h"
62 #include "my_alloc.h"
63 #include "my_base.h"
64 #include "my_bitmap.h"
65 #include "my_check_opt.h" // T_EXTEND
66 #include "my_checksum.h"
67 #include "my_compiler.h"
68 #include "my_dbug.h"
69 #include "my_io.h"
70 #include "my_loglevel.h"
71 #include "my_psi_config.h"
72 #include "my_sqlcommand.h"
73 #include "my_sys.h"
74 #include "my_systime.h"
75 #include "my_thread_local.h"
76 #include "my_time.h"
77 #include "mysql/components/services/bits/psi_bits.h"
78 #include "mysql/components/services/bits/psi_stage_bits.h"
79 #include "mysql/components/services/log_builtins.h"
80 #include "mysql/components/services/log_shared.h"
81 #include "mysql/plugin.h"
82 #include "mysql/psi/mysql_mutex.h"
83 #include "mysql/psi/mysql_stage.h"
84 #include "mysql_com.h"
85 #include "mysql_time.h"
86 #include "mysqld_error.h" // ER_*
87 #include "pfs_table_provider.h"
88 #include "prealloced_array.h"
89 #include "scope_guard.h"
90 #include "sql/auth/auth_acls.h"
91 #include "sql/auth/auth_common.h" // check_fk_parent_table_access
92 #include "sql/binlog.h" // mysql_bin_log
93 #include "sql/create_field.h"
94 #include "sql/current_thd.h"
95 #include "sql/dd/cache/dictionary_client.h" // dd::cache::Dictionary_client
96 #include "sql/dd/collection.h"
97 #include "sql/dd/dd.h" // dd::get_dictionary
98 #include "sql/dd/dd_schema.h" // dd::schema_exists
99 #include "sql/dd/dd_table.h" // dd::drop_table, dd::update_keys...
100 #include "sql/dd/dictionary.h" // dd::Dictionary
101 #include "sql/dd/impl/types/index_impl.h"
102 #include "sql/dd/properties.h" // dd::Properties
103 #include "sql/dd/sdi_api.h" // dd::sdi::drop_sdis
104 #include "sql/dd/string_type.h"
105 #include "sql/dd/types/abstract_table.h"
106 #include "sql/dd/types/check_constraint.h" // dd::Check_constraint
107 #include "sql/dd/types/column.h"
108 #include "sql/dd/types/foreign_key.h" // dd::Foreign_key
109 #include "sql/dd/types/foreign_key_element.h" // dd::Foreign_key_element
110 #include "sql/dd/types/index.h" // dd::Index
111 #include "sql/dd/types/index_element.h" // dd::Index_element
112 #include "sql/dd/types/partition.h" // dd::Partition
113 #include "sql/dd/types/schema.h"
114 #include "sql/dd/types/table.h" // dd::Table
115 #include "sql/dd/types/trigger.h"
116 #include "sql/dd_sql_view.h" // update_referencing_views_metadata
117 #include "sql/dd_table_share.h" // open_table_def
118 #include "sql/debug_sync.h" // DEBUG_SYNC
119 #include "sql/derror.h" // ER_THD
120 #include "sql/enum_query_type.h"
121 #include "sql/error_handler.h" // Drop_table_error_handler
122 #include "sql/field.h"
123 #include "sql/field_common_properties.h"
124 #include "sql/filesort.h" // Filesort
125 #include "sql/gis/srid.h"
126 #include "sql/handler.h"
127 #include "sql/histograms/histogram.h"
128 #include "sql/item.h"
129 #include "sql/item_timefunc.h" // Item_func_now_local
130 #include "sql/iterators/row_iterator.h"
131 #include "sql/join_optimizer/access_path.h"
132 #include "sql/join_optimizer/bit_utils.h"
133 #include "sql/key.h" // KEY
134 #include "sql/key_spec.h" // Key_part_spec
135 #include "sql/lock.h" // mysql_lock_remove, lock_tablespace_names
136 #include "sql/locked_tables_list.h"
137 #include "sql/log.h"
138 #include "sql/log_event.h" // Query_log_event
139 #include "sql/mdl.h"
140 #include "sql/mem_root_array.h"
141 #include "sql/my_decimal.h"
142 #include "sql/mysqld.h" // lower_case_table_names
143 #include "sql/partition_element.h"
144 #include "sql/partition_info.h" // partition_info
145 #include "sql/partitioning/partition_handler.h" // Partition_handler
146 #include "sql/protocol.h"
147 #include "sql/psi_memory_key.h"
148 #include "sql/query_options.h"
149 #include "sql/rpl_gtid.h"
150 #include "sql/rpl_rli.h" // rli_slave etc
151 #include "sql/session_tracker.h"
152 #include "sql/sql_alter.h"
153 #include "sql/sql_backup_lock.h" // acquire_shared_backup_lock
154 #include "sql/sql_base.h" // lock_table_names
155 #include "sql/sql_bitmap.h"
156 #include "sql/sql_check_constraint.h" // Sql_check_constraint_spec*
157 #include "sql/sql_class.h" // THD
158 #include "sql/sql_const.h"
159 #include "sql/sql_constraint.h" // Constraint_type_resolver
160 #include "sql/sql_db.h" // get_default_db_collation
161 #include "sql/sql_error.h"
162 #include "sql/sql_executor.h" // unique_ptr_destroy_only<RowIterator>
163 #include "sql/sql_gipk.h"
164 #include "sql/sql_handler.h"
165 #include "sql/sql_lex.h"
166 #include "sql/sql_list.h"
167 #include "sql/sql_parse.h" // test_if_data_home_dir
168 #include "sql/sql_partition.h"
169 #include "sql/sql_plist.h"
170 #include "sql/sql_plugin.h"
171 #include "sql/sql_plugin_ref.h"
172 #include "sql/sql_resolver.h" // setup_order
173 #include "sql/sql_show.h"
174 #include "sql/sql_tablespace.h" // validate_tablespace_name
175 #include "sql/sql_time.h" // make_truncated_value_warning
176 #include "sql/sql_trigger.h" // change_trigger_table_name
177 #include "sql/sql_zip_dict.h"
178 #include "sql/srs_fetcher.h"
179 #include "sql/stateless_allocator.h"
180 #include "sql/strfunc.h" // find_type2
181 #include "sql/system_variables.h"
182 #include "sql/table.h"
183 #include "sql/thd_raii.h"
184 #include "sql/thr_malloc.h"
185 #include "sql/transaction.h" // trans_commit_stmt
186 #include "sql/transaction_info.h"
187 #include "sql/trigger.h"
188 #include "sql/xa.h"
189 #include "sql_string.h"
190 #include "sql_zip_dict.h"
191 #include "template_utils.h"
192 #include "thr_lock.h"
193 #include "typelib.h"
194
195 namespace dd {
196 class View;
197 } // namespace dd
198
199 using binary_log::checksum_crc32;
200 using std::max;
201 using std::min;
202 using std::string;
203 using std::to_string;
204
205 /** Don't pack string keys shorter than this (if PACK_KEYS=1 isn't used). */
206 static constexpr const int KEY_DEFAULT_PACK_LENGTH{8};
207 /* Max number of enumeration values */
208 static constexpr const int MAX_ENUM_VALUES{65535};
209
210 #define ER_THD_OR_DEFAULT(thd, X) \
211 ((thd) ? ER_THD_NONCONST(thd, X) : ER_DEFAULT_NONCONST(X))
212
213 const char *primary_key_name = "PRIMARY";
214 namespace {
215 847809 bool is_temp_table(const HA_CREATE_INFO &ci) {
216 847809 return (ci.options & HA_LEX_CREATE_TMP_TABLE);
217 }
218
219 1342807 bool is_engine_specified(const HA_CREATE_INFO &ci) {
220
3/4
✓ Branch 0 taken 1102295 times.
✓ Branch 1 taken 240512 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1102295 times.
1342807 assert((ci.used_fields & HA_CREATE_USED_ENGINE) == 0 ||
221 ci.db_type != nullptr);
222 1342807 return (ci.used_fields & HA_CREATE_USED_ENGINE);
223 }
224
225 173641 handlerton *default_handlerton(THD *thd, const HA_CREATE_INFO &ci) {
226
2/2
✓ Branch 0 taken 44037 times.
✓ Branch 1 taken 129604 times.
173641 return is_temp_table(ci) ? ha_default_temp_handlerton(thd)
227 173641 : ha_default_handlerton(thd);
228 }
229
230 670931 handlerton *requested_handlerton(THD *thd, const HA_CREATE_INFO &ci) {
231
2/2
✓ Branch 0 taken 550677 times.
✓ Branch 1 taken 120254 times.
670931 return is_engine_specified(ci) ? ci.db_type : default_handlerton(thd, ci);
232 }
233
234 struct Handlerton_pair {
235 handlerton *requested;
236 handlerton *alternate;
237 };
238
239 using Viability_error_emitter = std::function<void(const char *engine_name)>;
240 using Viability_substitution_warning_emitter = std::function<void(
241 THD *, const char *requested_engine_name,
242 const char *substituted_engine_name, const char *table_name)>;
243
244 struct Viability {
245 bool value{true};
246 Viability_error_emitter emit_error;
247 Viability_substitution_warning_emitter emit_substitution_warning;
248 673015 Viability() = default;
249 45 Viability(Viability_error_emitter &&error_emitter,
250 Viability_substitution_warning_emitter &&warning_emitter)
251 45 : value{false},
252 45 emit_error{std::move(error_emitter)},
253 45 emit_substitution_warning{std::move(warning_emitter)} {
254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 assert(emit_error);
255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 assert(emit_substitution_warning);
256 45 }
257 };
258
259 673061 Viability get_viability(const handlerton &hton, const HA_CREATE_INFO &ci) {
260
1/2
✓ Branch 0 taken 673063 times.
✗ Branch 1 not taken.
673061 DBUG_TRACE;
261
3/4
✓ Branch 0 taken 673062 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 673023 times.
673063 if (ha_is_externally_disabled(hton)) {
262 27 return {[](const char *en) {
263 27 my_error(ER_DISABLED_STORAGE_ENGINE, MYF(0), en);
264 27 },
265 6 [](THD *t, const char *ren, const char *sen, const char *tn) {
266 6 push_warning_printf(t, Sql_condition::SL_WARNING,
267 ER_DISABLED_STORAGE_ENGINE,
268 ER_THD(t, ER_DISABLED_STORAGE_ENGINE), ren);
269 6 push_warning_printf(
270 t, Sql_condition::SL_WARNING, ER_WARN_USING_OTHER_HANDLER,
271 ER_THD(t, ER_WARN_USING_OTHER_HANDLER), sen, tn);
272 39 }};
273 }
274
6/6
✓ Branch 0 taken 51399 times.
✓ Branch 1 taken 621623 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 51393 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 673016 times.
724422 if (is_temp_table(ci) &&
275 51399 ha_check_storage_engine_flag(&hton, HTON_TEMPORARY_NOT_SUPPORTED)) {
276 return {
277 1 [](const char *en) {
278 1 my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), en, "TEMPORARY");
279 1 },
280 5 [](THD *, const char *, const char *,
281 6 const char *) { /* Nothing, no warning emitted in this case */ }};
282 }
283 673016 return {};
284 673062 }
285
286 672102 handlerton *get_viable_handlerton_for_create_impl(THD *thd,
287 const char *table_name,
288 const HA_CREATE_INFO &ci,
289 Handlerton_pair hp) {
290
1/2
✓ Branch 0 taken 672103 times.
✗ Branch 1 not taken.
672102 DBUG_TRACE;
291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 672103 times.
672103 assert(hp.requested != nullptr);
292
1/2
✓ Branch 0 taken 672104 times.
✗ Branch 1 not taken.
672103 auto viability = get_viability(*hp.requested, ci);
293
2/2
✓ Branch 0 taken 672069 times.
✓ Branch 1 taken 35 times.
672104 if (viability.value) {
294 672069 return hp.requested;
295 }
296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 assert(viability.emit_error);
297
298
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 const char *en = ha_resolve_storage_engine_name(hp.requested);
299
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 15 times.
35 if (hp.alternate == nullptr) {
300
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 viability.emit_error(en);
301 20 return nullptr;
302 }
303
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 auto alt_viability = get_viability(*hp.alternate, ci);
304
305
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 const char *an = ha_resolve_storage_engine_name(hp.alternate);
306
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 11 times.
15 if (!alt_viability.value) {
307
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 viability.emit_error(en);
308 4 return nullptr;
309 }
310
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 viability.emit_substitution_warning(thd, en, an, table_name);
311 11 return hp.alternate;
312 672104 }
313
314 /**
315 Check if source is enabled AND NOT explicitly disabled (listed in the
316 disabled_storages_engines system variable.
317
318 If not; falls back to the default (tmp) storage engine if substitution
319 is allowed, unless this is also disabled.
320
321 Otherwise, if substitution does take place, ER_DISABLED_STORAGE_ENGINE and
322 ER_USING_OTHER_HANDLER are emitted as warnings.
323
324 For temporary tables the above also applies, and in addition the source
325 handlerton is checked to see if it supports temporary tables.
326
327 Note that this substitution is allowed even when no_substitution is ON, but
328 will fail if the default handlerton for temporary tables is disabled or does
329 not support temporary tables (unlikely).
330
331 @param thd Thread handler.
332 @param table_name Table name.
333 @param ci create info struct from parser.
334 @param source Handlerton requested by query.
335
336 @retval source if this is viable.
337 @retval The default hton if viable and engine substitution is allowed.
338 @retval The default temp hton if viable and a temporary table and source
339 does not support temporary tables.
340 @retval nullptr if error (source not viable and substitution
341 not possible).
342 */
343 1171 handlerton *get_viable_handlerton_for_create_like(THD *thd,
344 const char *table_name,
345 const HA_CREATE_INFO &ci,
346 handlerton *source) {
347 1171 return get_viable_handlerton_for_create_impl(
348 thd, table_name, ci,
349
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 1071 times.
2317 {source, is_engine_substitution_allowed(thd) || is_temp_table(ci)
350
2/2
✓ Branch 0 taken 1146 times.
✓ Branch 1 taken 25 times.
2317 ? default_handlerton(thd, ci)
351 1171 : nullptr});
352 }
353
354 /**
355 Does nothing (returns existing) unless ALTER changes the ENGINE. The
356 handlerton for the specified ENGINE is considered viable if it is enabled AND
357 NOT explicitly disabled (listed in the disabled_storages_engines system
358 variable).
359
360 If the specified handleton is not viable it falls back to existing if
361 substitution is allowed. existing is used without further checking,
362 and ER_UNKNOWN_STORAGE_ENGINE is emitted as warning.
363
364 @param thd Thread handler.
365 @param ci create info struct from parser.
366 @param existing Handlerton requested by query.
367
368 @retval existing if ENGINE is not specified or is the same as existing, or if
369 ENGINE is not viable and substitution is permitted.
370 @retval Handlerton of specified engine if this is viable.
371 @retval nullptr if error (specified engine not viable and substitution
372 not permitted).
373 */
374 943 handlerton *get_viable_handlerton_for_alter(THD *thd, const HA_CREATE_INFO &ci,
375 handlerton *existing) {
376
1/2
✓ Branch 0 taken 943 times.
✗ Branch 1 not taken.
943 DBUG_TRACE;
377
3/6
✓ Branch 0 taken 943 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 943 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 943 times.
943 if (!is_engine_specified(ci) || ci.db_type == existing) return existing;
378
379 Handlerton_pair hp = {
380
2/2
✓ Branch 0 taken 586 times.
✓ Branch 1 taken 357 times.
943 ci.db_type, is_engine_substitution_allowed(thd) ? existing : nullptr};
381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 943 times.
943 assert(hp.requested != nullptr);
382
1/2
✓ Branch 0 taken 943 times.
✗ Branch 1 not taken.
943 auto viability = get_viability(*hp.requested, ci);
383
2/2
✓ Branch 0 taken 937 times.
✓ Branch 1 taken 6 times.
943 if (viability.value) {
384 937 return hp.requested;
385 }
386
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 const char *en = ha_resolve_storage_engine_name(hp.requested);
387
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (hp.alternate == nullptr) {
388
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 viability.emit_error(en);
389 4 return nullptr;
390 }
391
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_UNKNOWN_STORAGE_ENGINE,
392 ER_THD(thd, ER_UNKNOWN_STORAGE_ENGINE), en);
393 2 return hp.alternate;
394 943 }
395 } // namespace
396
397 /**
398 Checks if the handlerton for the specified ENGINE is enabled AND NOT
399 explicitly disabled (listed in the disabled_storages_engines system
400 variable). In the case of temporary tables the handlerton must also support
401 those to be viable.
402
403 When returning a handlerton different from the one specified
404 ER_DISABLED_STORAGE_ENGINE and ER_USING_OTHER_HANDLER are emitted as
405 warnings.
406
407 @param thd Thread handler.
408 @param table_name Table name.
409 @param ci create_info struct from parser.
410
411 @retval Handlerton for specified ENGINE if this is viable.
412 @retval The default (tmp) handlerton if viable and engine substitution is
413 allowed.
414 @retval nullptr if error (specified ENGINE not viable and substitution
415 not permitted).
416 */
417 670932 handlerton *get_viable_handlerton_for_create(THD *thd, const char *table_name,
418 const HA_CREATE_INFO &ci) {
419 670931 return get_viable_handlerton_for_create_impl(
420 thd, table_name, ci,
421 670932 {requested_handlerton(thd, ci),
422
2/2
✓ Branch 0 taken 53285 times.
✓ Branch 1 taken 497390 times.
1221609 (is_engine_specified(ci) && is_engine_substitution_allowed(thd))
423
2/2
✓ Branch 0 taken 550676 times.
✓ Branch 1 taken 120256 times.
1221607 ? default_handlerton(thd, ci)
424 670933 : nullptr});
425 }
426
427 static bool check_if_keyname_exists(const char *name, KEY *start, KEY *end);
428 static const char *make_unique_key_name(const char *field_name, KEY *start,
429 KEY *end);
430
431 static const dd::Index *find_fk_supporting_key(handlerton *hton,
432 const dd::Table *table_def,
433 const dd::Foreign_key *fk);
434
435 static const dd::Index *find_fk_parent_key(handlerton *hton,
436 const dd::Index *supporting_key,
437 const dd::Table *parent_table_def,
438 const dd::Foreign_key *fk);
439 static int copy_data_between_tables(
440 THD *thd, PSI_stage_progress *psi, TABLE *from, TABLE *to,
441 List<Create_field> &create, ha_rows *copied, ha_rows *deleted,
442 Alter_info::enum_enable_or_disable keys_onoff, Alter_table_ctx *alter_ctx,
443 bool expand_fast_index_creation);
444
445 static bool prepare_blob_field(THD *thd, Create_field *sql_field,
446 bool convert_character_set);
447 static bool check_engine(THD *thd, const char *db_name, const char *table_name,
448 HA_CREATE_INFO *create_info,
449 const Alter_info *alter_info);
450
451 static bool prepare_set_field(THD *thd, Create_field *sql_field);
452 static bool prepare_enum_field(THD *thd, Create_field *sql_field);
453
454 static uint blob_length_by_type(enum_field_types type);
455 static const Create_field *get_field_by_index(Alter_info *alter_info, uint idx);
456
457 static bool generate_check_constraint_name(THD *thd, const char *table_name,
458 uint ordinal_number,
459 LEX_STRING &name,
460 bool skip_validation);
461 static bool push_check_constraint_mdl_request_to_list(
462 THD *thd, const char *db, const char *cc_name,
463 MDL_request_list &cc_mdl_request_list);
464 static bool prepare_check_constraints_for_create_like_table(
465 THD *thd, TABLE_LIST *src_table, TABLE_LIST *table, Alter_info *alter_info);
466 static bool prepare_check_constraints_for_alter(THD *thd, const TABLE *table,
467 Alter_info *alter_info,
468 Alter_table_ctx *alter_tbl_ctx);
469 static void set_check_constraints_alter_mode(dd::Table *table,
470 Alter_info *alter_info);
471 static void reset_check_constraints_alter_mode(dd::Table *table);
472 static bool adjust_check_constraint_names_for_old_table_version(
473 THD *thd, const char *old_table_db, dd::Table *old_table);
474 static bool is_any_check_constraints_evaluation_required(
475 const Alter_info *alter_info);
476
477 static bool check_if_field_used_by_generated_column_or_default(
478 TABLE *table, const Field *field, const Alter_info *alter_info);
479
480 /**
481 RAII class to control the atomic DDL commit on slave.
482 A slave context flag responsible to mark the DDL as committed is
483 raised and kept for the entirety of DDL commit block.
484 While DDL commits the slave info table won't take part
485 in its transaction.
486 */
487 class Disable_slave_info_update_guard {
488 Relay_log_info *m_rli;
489 bool m_flag;
490
491 public:
492 3 Disable_slave_info_update_guard(THD *thd)
493 3 : m_rli(thd->rli_slave), m_flag(false) {
494
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!thd->slave_thread) {
495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(!m_rli);
496
497 3 return;
498 }
499
500 assert(m_rli->current_event);
501
502 m_flag = static_cast<Query_log_event *>(thd->rli_slave->current_event)
503 ->has_ddl_committed;
504 static_cast<Query_log_event *>(m_rli->current_event)->has_ddl_committed =
505 true;
506 }
507
508 3 ~Disable_slave_info_update_guard() {
509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (m_rli) {
510 static_cast<Query_log_event *>(m_rli->current_event)->has_ddl_committed =
511 m_flag;
512 }
513 3 }
514 };
515
516 172542 static bool trans_intermediate_ddl_commit(THD *thd, bool error) {
517 // Must be used for intermediate (but not final) DDL commits.
518
1/2
✓ Branch 0 taken 172542 times.
✗ Branch 1 not taken.
172542 Implicit_substatement_state_guard substatement_guard(thd);
519
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 172538 times.
172542 if (error) {
520
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 trans_rollback_stmt(thd);
521 // Full rollback in case we have THD::transaction_rollback_request.
522
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 trans_rollback(thd);
523 4 return true;
524 }
525
4/8
✓ Branch 0 taken 172538 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 172538 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 172538 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 172538 times.
172538 return trans_commit_stmt(thd) || trans_commit(thd);
526 172542 }
527
528 /**
529 @brief Helper function for explain_filename
530 @param thd Thread handle
531 @param to_p Explained name in system_charset_info
532 @param end_p End of the to_p buffer
533 @param name Name to be converted
534 @param name_len Length of the name, in bytes
535 */
536 32835 static char *add_identifier(THD *thd, char *to_p, const char *end_p,
537 const char *name, size_t name_len) {
538 size_t res;
539 uint errors;
540 const char *conv_name;
541 char tmp_name[FN_REFLEN];
542 char conv_string[FN_REFLEN];
543 int quote;
544
545
1/2
✓ Branch 0 taken 32835 times.
✗ Branch 1 not taken.
32835 DBUG_TRACE;
546
2/2
✓ Branch 0 taken 31201 times.
✓ Branch 1 taken 1634 times.
32835 if (!name[name_len])
547 31201 conv_name = name;
548 else {
549 1634 my_stpnmov(tmp_name, name, name_len);
550 1634 tmp_name[name_len] = 0;
551 1634 conv_name = tmp_name;
552 }
553
1/2
✓ Branch 0 taken 32835 times.
✗ Branch 1 not taken.
32835 res = strconvert(&my_charset_filename, conv_name, system_charset_info,
554 conv_string, FN_REFLEN, &errors);
555
3/4
✓ Branch 0 taken 32835 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 75 times.
✓ Branch 3 taken 32760 times.
32835 if (!res || errors) {
556
3/8
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 75 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 75 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
75 DBUG_PRINT("error", ("strconvert of '%s' failed with %u (errors: %u)",
557 conv_name, static_cast<uint>(res), errors));
558 75 conv_name = name;
559 } else {
560
3/8
✓ Branch 0 taken 32760 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32760 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 32760 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
32760 DBUG_PRINT("info", ("conv '%s' -> '%s'", conv_name, conv_string));
561 32760 conv_name = conv_string;
562 }
563
564
3/4
✓ Branch 0 taken 26234 times.
✓ Branch 1 taken 6601 times.
✓ Branch 2 taken 26234 times.
✗ Branch 3 not taken.
32835 quote = thd ? get_quote_char_for_identifier(thd, conv_name, res - 1) : '`';
565
566
2/4
✓ Branch 0 taken 32835 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32835 times.
✗ Branch 3 not taken.
32835 if (quote != EOF && (end_p - to_p > 2)) {
567 32835 *(to_p++) = (char)quote;
568
3/4
✓ Branch 0 taken 212717 times.
✓ Branch 1 taken 32835 times.
✓ Branch 2 taken 212717 times.
✗ Branch 3 not taken.
245552 while (*conv_name && (end_p - to_p - 1) > 0) {
569
1/2
✓ Branch 0 taken 212717 times.
✗ Branch 1 not taken.
212717 uint length = my_mbcharlen(system_charset_info, *conv_name);
570
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 212711 times.
212717 if (!length) length = 1;
571
3/4
✓ Branch 0 taken 212717 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 212705 times.
212717 if (length == 1 && *conv_name == (char)quote) {
572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if ((end_p - to_p) < 3) break;
573 12 *(to_p++) = (char)quote;
574 12 *(to_p++) = *(conv_name++);
575
1/2
✓ Branch 0 taken 212705 times.
✗ Branch 1 not taken.
212705 } else if (((long)length) < (end_p - to_p)) {
576 212705 to_p = my_stpnmov(to_p, conv_name, length);
577 212705 conv_name += length;
578 } else
579 break; /* string already filled */
580 }
581
1/2
✓ Branch 0 taken 32835 times.
✗ Branch 1 not taken.
32835 if (end_p > to_p) {
582 32835 *(to_p++) = (char)quote;
583
1/2
✓ Branch 0 taken 32835 times.
✗ Branch 1 not taken.
32835 if (end_p > to_p)
584 32835 *to_p = 0; /* terminate by NUL, but do not include it in the count */
585 }
586 32835 } else
587 to_p = my_stpnmov(to_p, conv_name, end_p - to_p);
588 32835 return to_p;
589 32835 }
590
591 /**
592 @brief Explain a path name by split it to database, table etc.
593
594 @details Break down the path name to its logic parts
595 (database, table, partition, subpartition).
596 filename_to_tablename cannot be used on partitions, due to the @#P@# part.
597 There can be up to 6 '#', @#P@# for partition, @#SP@# for subpartition
598 and @#TMP@# or @#REN@# for temporary or renamed partitions.
599 This should be used when something should be presented to a user in a
600 diagnostic, error etc. when it would be useful to know what a particular
601 file [and directory] means. Such as SHOW ENGINE STATUS, error messages etc.
602
603 Examples:
604
605 t1#P#p1 table t1 partition p1
606 t1#P#p1#SP#sp1 table t1 partition p1 subpartition sp1
607 t1#P#p1#SP#sp1#TMP# table t1 partition p1 subpartition sp1 temporary
608 t1#P#p1#SP#sp1#REN# table t1 partition p1 subpartition sp1 renamed
609
610 @param thd Thread handle
611 @param from Path name in my_charset_filename
612 Null terminated in my_charset_filename, normalized
613 to use '/' as directory separation character.
614 @param to Explained name in system_charset_info
615 @param to_length Size of to buffer
616 @param explain_mode Requested output format.
617 EXPLAIN_ALL_VERBOSE ->
618 [Database `db`, ]Table `tbl`[,[ Temporary| Renamed]
619 Partition `p` [, Subpartition `sp`]]
620 EXPLAIN_PARTITIONS_VERBOSE -> `db`.`tbl`
621 [[ Temporary| Renamed] Partition `p`
622 [, Subpartition `sp`]]
623 EXPLAIN_PARTITIONS_AS_COMMENT -> `db`.`tbl` |*
624 [,[ Temporary| Renamed] Partition `p`
625 [, Subpartition `sp`]] *|
626 (| is really a /, and it is all in one line)
627
628 @retval Length of returned string
629 */
630
631 31210 size_t explain_filename(THD *thd, const char *from, char *to, size_t to_length,
632 enum_explain_filename_mode explain_mode) {
633 31210 char *to_p = to;
634 31210 char *end_p = to_p + to_length;
635 31210 const char *db_name = nullptr;
636 31210 size_t db_name_len = 0;
637 const char *table_name;
638 31210 size_t table_name_len = 0;
639 31210 const char *part_name = nullptr;
640 31210 size_t part_name_len = 0;
641 31210 const char *subpart_name = nullptr;
642 31210 size_t subpart_name_len = 0;
643 31210 enum enum_part_name_type { NORMAL, TEMP, RENAMED } part_type = NORMAL;
644
645 const char *tmp_p;
646
1/2
✓ Branch 0 taken 31210 times.
✗ Branch 1 not taken.
31210 DBUG_TRACE;
647
3/8
✓ Branch 0 taken 31210 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31210 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 31210 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
31210 DBUG_PRINT("enter", ("from '%s'", from));
648 31210 tmp_p = from;
649 31210 table_name = from;
650 /*
651 If '/' then take last directory part as database.
652 '/' is the directory separator, not FN_LIB_CHAR
653 */
654
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 31210 times.
31270 while ((tmp_p = strchr(tmp_p, '/'))) {
655 60 db_name = table_name;
656 /* calculate the length */
657 60 db_name_len = tmp_p - db_name;
658 60 tmp_p++;
659 60 table_name = tmp_p;
660 }
661 31210 tmp_p = table_name;
662 /* Look if there are partition tokens in the table name. */
663 31210 while ((tmp_p = strchr(tmp_p, '#'))) {
664 1642 tmp_p++;
665
5/5
✓ Branch 0 taken 1258 times.
✓ Branch 1 taken 354 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 9 times.
1642 switch (tmp_p[0]) {
666 1258 case 'P':
667 case 'p':
668
2/2
✓ Branch 0 taken 1255 times.
✓ Branch 1 taken 3 times.
1258 if (tmp_p[1] == '#') {
669 1255 part_name = tmp_p + 2;
670 1255 tmp_p += 2;
671 }
672 1258 break;
673 354 case 'S':
674 case 's':
675
5/6
✓ Branch 0 taken 329 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 288 times.
✓ Branch 3 taken 41 times.
✓ Branch 4 taken 313 times.
✗ Branch 5 not taken.
354 if ((tmp_p[1] == 'P' || tmp_p[1] == 'p') && tmp_p[2] == '#') {
676 313 part_name_len = tmp_p - part_name - 1;
677 313 subpart_name = tmp_p + 3;
678 313 tmp_p += 3;
679 }
680 354 break;
681 15 case 'T':
682 case 't':
683
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
15 if ((tmp_p[1] == 'M' || tmp_p[1] == 'm') &&
684
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
9 (tmp_p[2] == 'P' || tmp_p[2] == 'p') && tmp_p[3] == '#' &&
685
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 !tmp_p[4]) {
686 9 part_type = TEMP;
687 9 tmp_p += 4;
688 }
689 15 break;
690 6 case 'R':
691 case 'r':
692
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 if ((tmp_p[1] == 'E' || tmp_p[1] == 'e') &&
693
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
6 (tmp_p[2] == 'N' || tmp_p[2] == 'n') && tmp_p[3] == '#' &&
694
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 !tmp_p[4]) {
695 6 part_type = RENAMED;
696 6 tmp_p += 4;
697 }
698 6 break;
699
2/2
✓ Branch 0 taken 1642 times.
✓ Branch 1 taken 31210 times.
32852 default:
700 /* Not partition name part. */
701 ;
702 }
703 }
704
2/2
✓ Branch 0 taken 1255 times.
✓ Branch 1 taken 29955 times.
31210 if (part_name) {
705 1255 table_name_len = part_name - table_name - 3;
706
2/2
✓ Branch 0 taken 310 times.
✓ Branch 1 taken 945 times.
1255 if (subpart_name)
707 310 subpart_name_len = strlen(subpart_name);
708 else
709 945 part_name_len = strlen(part_name);
710
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1246 times.
1255 if (part_type != NORMAL) {
711
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (subpart_name)
712 9 subpart_name_len -= 5;
713 else
714 part_name_len -= 5;
715 }
716 } else
717 29955 table_name_len = strlen(table_name);
718
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 31150 times.
31210 if (db_name) {
719
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 42 times.
60 if (explain_mode == EXPLAIN_ALL_VERBOSE) {
720
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 to_p = my_stpncpy(to_p, ER_THD_OR_DEFAULT(thd, ER_DATABASE_NAME),
721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 end_p - to_p);
722 18 *(to_p++) = ' ';
723
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 to_p = add_identifier(thd, to_p, end_p, db_name, db_name_len);
724 18 to_p = my_stpncpy(to_p, ", ", end_p - to_p);
725 } else {
726
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 to_p = add_identifier(thd, to_p, end_p, db_name, db_name_len);
727 42 to_p = my_stpncpy(to_p, ".", end_p - to_p);
728 }
729 }
730
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 31192 times.
31210 if (explain_mode == EXPLAIN_ALL_VERBOSE) {
731 to_p =
732
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
18 my_stpncpy(to_p, ER_THD_OR_DEFAULT(thd, ER_TABLE_NAME), end_p - to_p);
733 18 *(to_p++) = ' ';
734
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 to_p = add_identifier(thd, to_p, end_p, table_name, table_name_len);
735 } else
736
1/2
✓ Branch 0 taken 31192 times.
✗ Branch 1 not taken.
31192 to_p = add_identifier(thd, to_p, end_p, table_name, table_name_len);
737
2/2
✓ Branch 0 taken 1255 times.
✓ Branch 1 taken 29955 times.
31210 if (part_name) {
738
2/2
✓ Branch 0 taken 1252 times.
✓ Branch 1 taken 3 times.
1255 if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT)
739 1252 to_p = my_stpncpy(to_p, " /* ", end_p - to_p);
740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 else if (explain_mode == EXPLAIN_PARTITIONS_VERBOSE)
741 to_p = my_stpncpy(to_p, " ", end_p - to_p);
742 else
743 3 to_p = my_stpncpy(to_p, ", ", end_p - to_p);
744
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1246 times.
1255 if (part_type != NORMAL) {
745
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 if (part_type == TEMP)
746
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 to_p = my_stpncpy(to_p, ER_THD_OR_DEFAULT(thd, ER_TEMPORARY_NAME),
747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 end_p - to_p);
748 else
749
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 to_p = my_stpncpy(to_p, ER_THD_OR_DEFAULT(thd, ER_RENAMED_NAME),
750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 end_p - to_p);
751 9 to_p = my_stpncpy(to_p, " ", end_p - to_p);
752 }
753
2/4
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1218 times.
✗ Branch 3 not taken.
1255 to_p = my_stpncpy(to_p, ER_THD_OR_DEFAULT(thd, ER_PARTITION_NAME),
754
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 1218 times.
1255 end_p - to_p);
755 1255 *(to_p++) = ' ';
756
1/2
✓ Branch 0 taken 1255 times.
✗ Branch 1 not taken.
1255 to_p = add_identifier(thd, to_p, end_p, part_name, part_name_len);
757
2/2
✓ Branch 0 taken 310 times.
✓ Branch 1 taken 945 times.
1255 if (subpart_name) {
758 310 to_p = my_stpncpy(to_p, ", ", end_p - to_p);
759
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 310 times.
✗ Branch 3 not taken.
310 to_p = my_stpncpy(to_p, ER_THD_OR_DEFAULT(thd, ER_SUBPARTITION_NAME),
760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 310 times.
310 end_p - to_p);
761 310 *(to_p++) = ' ';
762
1/2
✓ Branch 0 taken 310 times.
✗ Branch 1 not taken.
310 to_p = add_identifier(thd, to_p, end_p, subpart_name, subpart_name_len);
763 }
764
2/2
✓ Branch 0 taken 1252 times.
✓ Branch 1 taken 3 times.
1255 if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT)
765 1252 to_p = my_stpncpy(to_p, " */", end_p - to_p);
766 }
767
3/8
✓ Branch 0 taken 31210 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31210 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 31210 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
31210 DBUG_PRINT("exit", ("to '%s'", to));
768 31210 return static_cast<size_t>(to_p - to);
769 31210 }
770
771 /*
772 Translate a file name to a table name (WL #1324).
773
774 SYNOPSIS
775 filename_to_tablename()
776 from The file name in my_charset_filename.
777 to OUT The table name in system_charset_info.
778 to_length The size of the table name buffer.
779
780 RETURN
781 Table name length.
782 */
783
784 39338093 size_t filename_to_tablename(const char *from, char *to, size_t to_length,
785 bool stay_quiet) {
786 uint errors;
787 size_t res;
788
1/2
✓ Branch 0 taken 39338201 times.
✗ Branch 1 not taken.
39338093 DBUG_TRACE;
789
5/8
✓ Branch 0 taken 39338189 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39338155 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 208 times.
✓ Branch 5 taken 39337947 times.
✓ Branch 6 taken 208 times.
✗ Branch 7 not taken.
39338201 DBUG_PRINT("enter", ("from '%s'", from));
790
791
2/2
✓ Branch 0 taken 36577232 times.
✓ Branch 1 taken 2760923 times.
39338155 if (strlen(from) >= tmp_file_prefix_length &&
792
2/2
✓ Branch 0 taken 654820 times.
✓ Branch 1 taken 35922412 times.
36577232 !memcmp(from, tmp_file_prefix, tmp_file_prefix_length)) {
793 /* Temporary table name. */
794 654820 res = (my_stpnmov(to, from, to_length) - to);
795 } else {
796
1/2
✓ Branch 0 taken 38683368 times.
✗ Branch 1 not taken.
38683335 res = strconvert(&my_charset_filename, from, system_charset_info, to,
797 to_length, &errors);
798
2/2
✓ Branch 0 taken 436072 times.
✓ Branch 1 taken 38247296 times.
38683368 if (errors) // Old 5.0 name
799 {
800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 436072 times.
436072 if (!stay_quiet) {
801 LogErr(ERROR_LEVEL, ER_INVALID_OR_OLD_TABLE_OR_DB_NAME, from);
802 }
803 /*
804 TODO: add a stored procedure for fix table and database names,
805 and mention its name in error log.
806 */
807 }
808 }
809
810
5/8
✓ Branch 0 taken 39338132 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39338151 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 204 times.
✓ Branch 5 taken 39337947 times.
✓ Branch 6 taken 204 times.
✗ Branch 7 not taken.
39338188 DBUG_PRINT("exit", ("to '%s'", to));
811 39338203 return res;
812 39338151 }
813
814 /*
815 Translate a table name to a file name (WL #1324).
816
817 SYNOPSIS
818 tablename_to_filename()
819 from The table name in system_charset_info.
820 to OUT The file name in my_charset_filename.
821 to_length The size of the file name buffer.
822
823 RETURN
824 File name length.
825 */
826
827 9896742 size_t tablename_to_filename(const char *from, char *to, size_t to_length) {
828 uint errors;
829 size_t length;
830
1/2
✓ Branch 0 taken 9896751 times.
✗ Branch 1 not taken.
9896742 DBUG_TRACE;
831
5/8
✓ Branch 0 taken 9896750 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9896751 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 319 times.
✓ Branch 5 taken 9896432 times.
✓ Branch 6 taken 319 times.
✗ Branch 7 not taken.
9896751 DBUG_PRINT("enter", ("from '%s'", from));
832
833
1/2
✓ Branch 0 taken 9896749 times.
✗ Branch 1 not taken.
9896751 length = strconvert(system_charset_info, from, &my_charset_filename, to,
834 to_length, &errors);
835
6/8
✓ Branch 0 taken 9896748 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 9896738 times.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 9896738 times.
9896749 if (check_if_legal_tablename(to) && length + 4 < to_length) {
836 10 memcpy(to + length, "@@@", 4);
837 10 length += 3;
838 }
839
5/8
✓ Branch 0 taken 9896750 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9896751 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 313 times.
✓ Branch 5 taken 9896438 times.
✓ Branch 6 taken 313 times.
✗ Branch 7 not taken.
9896748 DBUG_PRINT("exit", ("to '%s'", to));
840 9896751 return length;
841 9896751 }
842
843 /*
844 @brief Creates path to a file: mysql_data_dir/db/table.ext
845
846 @param buff Where to write result in my_charset_filename.
847 This may be the same as table_name.
848 @param bufflen buff size
849 @param db Database name in system_charset_info.
850 @param table_name Table name in system_charset_info.
851 @param ext File extension.
852 @param flags FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
853 table_name is temporary, do not change.
854 @param was_truncated points to location that will be
855 set to true if path was truncated,
856 to false otherwise.
857
858 @note
859 Uses database and table name, and extension to create
860 a file name in mysql_data_dir. Database and table
861 names are converted from system_charset_info into "fscs".
862 Unless flags indicate a temporary table name.
863 'db' is always converted.
864 'ext' is not converted.
865
866 The conversion suppression is required for ALTER TABLE. This
867 statement creates intermediate tables. These are regular
868 (non-temporary) tables with a temporary name. Their path names must
869 be derivable from the table name. So we cannot use
870 build_tmptable_filename() for them.
871
872 @return
873 path length
874 */
875
876 4921885 size_t build_table_filename(char *buff, size_t bufflen, const char *db,
877 const char *table_name, const char *ext, uint flags,
878 bool *was_truncated) {
879 char tbbuff[FN_REFLEN], dbbuff[FN_REFLEN];
880 size_t tab_len, db_len;
881
1/2
✓ Branch 0 taken 4921892 times.
✗ Branch 1 not taken.
4921885 DBUG_TRACE;
882
5/8
✓ Branch 0 taken 4921892 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4921892 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 160 times.
✓ Branch 5 taken 4921732 times.
✓ Branch 6 taken 160 times.
✗ Branch 7 not taken.
4921892 DBUG_PRINT("enter", ("db: '%s' table_name: '%s' ext: '%s' flags: %x", db,
883 table_name, ext, flags));
884
885
2/2
✓ Branch 0 taken 146593 times.
✓ Branch 1 taken 4775295 times.
4921888 if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP
886 146593 tab_len = my_stpnmov(tbbuff, table_name, sizeof(tbbuff)) - tbbuff;
887 else
888
1/2
✓ Branch 0 taken 4775300 times.
✗ Branch 1 not taken.
4775295 tab_len = tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
889
890
1/2
✓ Branch 0 taken 4921893 times.
✗ Branch 1 not taken.
4921893 db_len = tablename_to_filename(db, dbbuff, sizeof(dbbuff));
891
892 4921893 char *end = buff + bufflen;
893 /* Don't add FN_ROOTDIR if mysql_data_home already includes it */
894 4921893 char *pos = my_stpnmov(buff, mysql_data_home, bufflen);
895 4921890 size_t rootdir_len = strlen(FN_ROOTDIR);
896
1/2
✓ Branch 0 taken 4921891 times.
✗ Branch 1 not taken.
4921890 if (pos - rootdir_len >= buff &&
897
2/2
✓ Branch 0 taken 4921885 times.
✓ Branch 1 taken 6 times.
4921891 memcmp(pos - rootdir_len, FN_ROOTDIR, rootdir_len) != 0)
898 4921885 pos = my_stpnmov(pos, FN_ROOTDIR, end - pos);
899 else
900 5 rootdir_len = 0;
901
1/2
✓ Branch 0 taken 4921888 times.
✗ Branch 1 not taken.
4921896 pos = strxnmov(pos, end - pos, dbbuff, FN_ROOTDIR, NullS);
902
1/2
✓ Branch 0 taken 4921886 times.
✗ Branch 1 not taken.
4921888 pos = strxnmov(pos, end - pos, tbbuff, ext, NullS);
903
904 /**
905 Mark OUT param if path gets truncated.
906 Most of functions which invoke this function are sure that the
907 path will not be truncated. In case some functions are not sure,
908 we can use 'was_truncated' OUTPARAM
909 */
910 4921886 *was_truncated = false;
911
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4921884 times.
4921886 if (pos == end && (bufflen < mysql_data_home_len + rootdir_len + db_len +
912
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 strlen(FN_ROOTDIR) + tab_len + strlen(ext)))
913 1 *was_truncated = true;
914
915
5/8
✓ Branch 0 taken 4921893 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4921893 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 157 times.
✓ Branch 5 taken 4921736 times.
✓ Branch 6 taken 157 times.
✗ Branch 7 not taken.
4921886 DBUG_PRINT("exit", ("buff: '%s'", buff));
916 4921892 return pos - buff;
917 4921893 }
918
919 /**
920 Create path to a temporary table, like mysql_tmpdir/@#sql1234_12_1
921 (i.e. to its .FRM file but without an extension).
922
923 @param thd The thread handle.
924 @param buff Where to write result in my_charset_filename.
925 @param bufflen buff size
926
927 @note
928 Uses current_pid, thread_id, and tmp_table counter to create
929 a file name in mysql_tmpdir.
930
931 @return Path length.
932 */
933
934 52574 size_t build_tmptable_filename(THD *thd, char *buff, size_t bufflen) {
935
1/2
✓ Branch 0 taken 52574 times.
✗ Branch 1 not taken.
52574 DBUG_TRACE;
936
937
1/2
✓ Branch 0 taken 52574 times.
✗ Branch 1 not taken.
52574 char *p = my_stpnmov(buff, mysql_tmpdir, bufflen);
938 assert(sizeof(my_thread_id) == 4);
939 105148 snprintf(p, bufflen - (p - buff), "/%s%lx_%x_%x", tmp_file_prefix,
940 52574 current_pid, thd->thread_id(), thd->tmp_table++);
941
942
2/2
✓ Branch 0 taken 244 times.
✓ Branch 1 taken 52330 times.
52574 if (lower_case_table_names) {
943 /* Convert all except tmpdir to lower case */
944
1/2
✓ Branch 0 taken 244 times.
✗ Branch 1 not taken.
244 my_casedn_str(files_charset_info, p);
945 }
946
947
1/2
✓ Branch 0 taken 52573 times.
✗ Branch 1 not taken.
52574 size_t length = unpack_filename(buff, buff);
948
3/8
✓ Branch 0 taken 52574 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52574 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 52574 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
52573 DBUG_PRINT("exit", ("buff: '%s'", buff));
949 52574 return length;
950 52574 }
951
952 /**
953 Create a dd::Table-object specifying the temporary table
954 definition, but do not put it into the Data Dictionary. The created
955 dd::Table-instance is returned via tmp_table_def out-parameter.
956 The temporary table is also created in the storage engine, depending
957 on the 'no_ha_table' argument.
958
959 @param thd Thread handler
960 @param path Name of file (including database)
961 @param sch_obj Schema.
962 @param db Schema name.
963 Cannot use dd::Schema::name() directly due to LCTN.
964 @param table_name Table name
965 @param create_info create info parameters
966 @param create_fields Fields to create
967 @param keys number of keys to create
968 @param key_info Keys to create
969 @param keys_onoff Enable or disable keys.
970 @param check_cons_spec List of check constraint specification.
971 @param file Handler to use
972 @param no_ha_table Indicates that only definitions needs to be created
973 and not a table in the storage engine.
974 @param[out] binlog_to_trx_cache
975 Which binlog cache should be used?
976 If true => trx cache
977 If false => stmt cache
978 @param[out] tmp_table_def Data-dictionary object for temporary table
979 which was created. Is not set if no_ha_table
980 was false.
981
982 @retval false ok
983 @retval true error
984 */
985
986 52459 static bool rea_create_tmp_table(
987 THD *thd, const char *path, const dd::Schema &sch_obj, const char *db,
988 const char *table_name, HA_CREATE_INFO *create_info,
989 List<Create_field> &create_fields, uint keys, KEY *key_info,
990 Alter_info::enum_enable_or_disable keys_onoff,
991 const Sql_check_constraint_spec_list *check_cons_spec, handler *file,
992 bool no_ha_table, bool *binlog_to_trx_cache,
993 std::unique_ptr<dd::Table> *tmp_table_def) {
994
1/2
✓ Branch 0 taken 52460 times.
✗ Branch 1 not taken.
52459 DBUG_TRACE;
995
996 std::unique_ptr<dd::Table> tmp_table_ptr =
997 dd::create_tmp_table(thd, sch_obj, table_name, create_info, create_fields,
998
2/4
✓ Branch 0 taken 52460 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52460 times.
✗ Branch 3 not taken.
52460 key_info, keys, keys_onoff, check_cons_spec, file);
999
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 52457 times.
52460 if (!tmp_table_ptr) return true;
1000
1001
2/2
✓ Branch 0 taken 1151 times.
✓ Branch 1 taken 51306 times.
52457 if (no_ha_table) {
1002 1151 *tmp_table_def = std::move(tmp_table_ptr);
1003 1151 return false;
1004 }
1005
1006 // Create the table in the storage engine.
1007
3/4
✓ Branch 0 taken 51304 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
✓ Branch 3 taken 51196 times.
51306 if (ha_create_table(thd, path, db, table_name, create_info, &create_fields,
1008 false, false, tmp_table_ptr.get())) {
1009 108 return true;
1010 }
1011
1012 /*
1013 Open a table (skipping table cache) and add it into
1014 THD::temporary_tables list.
1015 */
1016
1/2
✓ Branch 0 taken 51196 times.
✗ Branch 1 not taken.
51196 TABLE *table = open_table_uncached(thd, path, db, table_name, true, true,
1017 51196 *tmp_table_ptr.get());
1018
1019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51196 times.
51196 if (!table) {
1020 (void)rm_temporary_table(thd, create_info->db_type, path,
1021 tmp_table_ptr.get());
1022 return true;
1023 }
1024
1025 // Transfer ownership of dd::Table object to TABLE_SHARE.
1026 51196 table->s->tmp_table_def = tmp_table_ptr.release();
1027
1028 51196 thd->thread_specific_used = true;
1029
1030
2/2
✓ Branch 0 taken 50323 times.
✓ Branch 1 taken 873 times.
51196 if (binlog_to_trx_cache != nullptr)
1031 50323 *binlog_to_trx_cache = table->file->has_transactions();
1032 51196 return false;
1033 52458 }
1034
1035 /**
1036 Create table definition in the Data Dictionary. The table is also
1037 created in the storage engine, depending on the 'no_ha_table' argument.
1038
1039 @param thd Thread handler
1040 @param path Name of file (including database)
1041 @param sch_obj Schema.
1042 @param db Schema name.
1043 Cannot use dd::Schema::name() directly due to
1044 LCTN.
1045 @param table_name Table name
1046 @param create_info create info parameters
1047 @param create_fields Fields to create
1048 @param keys number of keys to create
1049 @param key_info Keys to create
1050 @param keys_onoff Enable or disable keys.
1051 @param fk_keys Number of foreign keys to create
1052 @param fk_key_info Foreign keys to create
1053 @param check_cons_spec List of check constraint specifications.
1054 @param file Handler to use
1055 @param no_ha_table Indicates that only definitions needs to be
1056 created and not a table in the storage engine.
1057 @param do_not_store_in_dd Indicates that we should postpone storing table
1058 object in the data-dictionary. Requires SE
1059 supporting atomic DDL and no_ha_table flag set.
1060 @param part_info Reference to partitioning data structure.
1061 @param[out] binlog_to_trx_cache
1062 Which binlog cache should be used?
1063 If true => trx cache
1064 If false => stmt cache
1065 @param[out] table_def_ptr dd::Table object describing the table
1066 created if do_not_store_in_dd option was
1067 used. Not set otherwise.
1068 @param[out] post_ddl_ht Set to handlerton for table's SE, if this SE
1069 supports atomic DDL, so caller can call SE
1070 post DDL hook after committing transaction.
1071
1072 @note For engines supporting atomic DDL the caller must rollback
1073 both statement and transaction on failure. This must be done
1074 before any further accesses to DD. @sa dd::create_table().
1075
1076 @retval false ok
1077 @retval true error
1078 */
1079
1080 690936 static bool rea_create_base_table(
1081 THD *thd, const char *path, const dd::Schema &sch_obj, const char *db,
1082 const char *table_name, HA_CREATE_INFO *create_info,
1083 List<Create_field> &create_fields, uint keys, KEY *key_info,
1084 Alter_info::enum_enable_or_disable keys_onoff, uint fk_keys,
1085 FOREIGN_KEY *fk_key_info,
1086 const Sql_check_constraint_spec_list *check_cons_spec, handler *file,
1087 bool no_ha_table, bool do_not_store_in_dd, partition_info *part_info,
1088 bool *binlog_to_trx_cache, std::unique_ptr<dd::Table> *table_def_ptr,
1089 handlerton **post_ddl_ht) {
1090
1/2
✓ Branch 0 taken 690948 times.
✗ Branch 1 not taken.
690936 DBUG_TRACE;
1091
1092 std::unique_ptr<dd::Table> table_def_res = dd::create_table(
1093 thd, sch_obj, table_name, create_info, create_fields, key_info, keys,
1094
2/4
✓ Branch 0 taken 690948 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 690938 times.
✗ Branch 3 not taken.
690948 keys_onoff, fk_key_info, fk_keys, check_cons_spec, file);
1095
1096
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 690845 times.
690949 if (!table_def_res) return true;
1097
1098
1/2
✓ Branch 0 taken 690835 times.
✗ Branch 1 not taken.
690845 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
1099 690835 dd::Table *table_def = nullptr;
1100
1101
2/2
✓ Branch 0 taken 61933 times.
✓ Branch 1 taken 628902 times.
690835 if (do_not_store_in_dd) {
1102 /*
1103 Clean up code assumes that SE supports atomic DDL if do_not_store_in_dd
1104 was requested, so we can simply rollback our changes.
1105
1106 ha_create_table() won't work correctly if dd::Table object is not stored
1107 in the data-dictionary.
1108
1109 For data-dictionary tables we rely on Dictionary_client::store() to update
1110 their table definition.
1111 */
1112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61933 times.
61933 assert(create_info->db_type->flags & HTON_SUPPORTS_ATOMIC_DDL);
1113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61933 times.
61933 assert(no_ha_table);
1114
5/10
✓ Branch 0 taken 61933 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 61933 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 61933 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 61933 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 61933 times.
61933 assert(!dd::get_dictionary()->get_dd_table(db, table_name));
1115
1116 61933 *table_def_ptr = std::move(table_def_res);
1117
1118 61933 table_def = table_def_ptr->get();
1119 } else {
1120
1/2
✓ Branch 0 taken 628914 times.
✗ Branch 1 not taken.
628902 bool result = thd->dd_client()->store(table_def_res.get());
1121
1122
4/4
✓ Branch 0 taken 114199 times.
✓ Branch 1 taken 514715 times.
✓ Branch 2 taken 96892 times.
✓ Branch 3 taken 532022 times.
743113 if (!(create_info->db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) &&
1123
2/2
✓ Branch 0 taken 96892 times.
✓ Branch 1 taken 17307 times.
114199 !thd->is_plugin_fake_ddl())
1124
1/2
✓ Branch 0 taken 96892 times.
✗ Branch 1 not taken.
96892 result = trans_intermediate_ddl_commit(thd, result);
1125
1126
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 628879 times.
628914 if (result) return true;
1127
1128
4/8
✓ Branch 0 taken 628880 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 628880 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 628879 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 628879 times.
628879 if (thd->dd_client()->acquire_for_modification(db, table_name, &table_def))
1129 return true;
1130 }
1131
1132
2/2
✓ Branch 0 taken 488760 times.
✓ Branch 1 taken 202052 times.
690812 if (no_ha_table) {
1133
2/2
✓ Branch 0 taken 2728 times.
✓ Branch 1 taken 486032 times.
488760 if (part_info) {
1134 /*
1135 For partitioned tables we can't find some problems with table
1136 until table is opened. Therefore in order to disallow creation
1137 of corrupted tables we have to try to open table as the part
1138 of its creation process.
1139 In cases when both .FRM and SE part of table are created table
1140 is implicitly open in ha_create_table() call.
1141 In cases when we create .FRM without SE part we have to open
1142 table explicitly.
1143 */
1144
1/2
✓ Branch 0 taken 2728 times.
✗ Branch 1 not taken.
2728 TABLE table;
1145
1/2
✓ Branch 0 taken 2728 times.
✗ Branch 1 not taken.
2728 TABLE_SHARE share;
1146
1147
1/2
✓ Branch 0 taken 2728 times.
✗ Branch 1 not taken.
2728 init_tmp_table_share(thd, &share, db, 0, table_name, path, nullptr);
1148
1149
2/4
✓ Branch 0 taken 2728 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2728 times.
✗ Branch 3 not taken.
5456 bool result = open_table_def(thd, &share, *table_def) ||
1150
3/4
✓ Branch 0 taken 2728 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 2692 times.
2728 open_table_from_share(thd, &share, "", 0, (uint)READ_ALL, 0,
1151 2728 &table, true, nullptr);
1152
1153 /*
1154 Assert that the change list is empty as no partition function currently
1155 needs to modify item tree. May need call THD::rollback_item_tree_changes
1156 later before calling closefrm if the change list is not empty.
1157 */
1158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2728 times.
2728 assert(thd->change_list.is_empty());
1159
3/4
✓ Branch 0 taken 2692 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 2692 times.
✗ Branch 3 not taken.
2728 if (!result) (void)closefrm(&table, false);
1160
1161
1/2
✓ Branch 0 taken 2728 times.
✗ Branch 1 not taken.
2728 free_table_share(&share);
1162
1163
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 2692 times.
2728 if (result) {
1164 /*
1165 If changes were committed remove table from DD.
1166 We ignore the errors returned from there functions
1167 as we anyway report error.
1168 */
1169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!(create_info->db_type->flags & HTON_SUPPORTS_ATOMIC_DDL)) {
1170 bool drop_result = dd::drop_table(thd, db, table_name, *table_def);
1171 (void)trans_intermediate_ddl_commit(thd, drop_result);
1172 }
1173
1174 36 return true;
1175 }
1176
4/4
✓ Branch 0 taken 2692 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 2692 times.
✓ Branch 3 taken 36 times.
2764 }
1177
1178 488724 return false;
1179 }
1180
1181
2/2
✓ Branch 0 taken 121256 times.
✓ Branch 1 taken 80796 times.
202052 if ((create_info->db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) &&
1182
1/2
✓ Branch 0 taken 121256 times.
✗ Branch 1 not taken.
121256 create_info->db_type->post_ddl)
1183 121256 *post_ddl_ht = create_info->db_type;
1184
1185
3/4
✓ Branch 0 taken 202030 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1018 times.
✓ Branch 3 taken 201012 times.
202052 if (ha_create_table(thd, path, db, table_name, create_info, &create_fields,
1186 false, false, table_def)) {
1187 /*
1188 Remove table from data-dictionary if it was added and rollback
1189 won't do this automatically.
1190 */
1191
2/2
✓ Branch 0 taken 279 times.
✓ Branch 1 taken 739 times.
1018 if (!(create_info->db_type->flags & HTON_SUPPORTS_ATOMIC_DDL)) {
1192 /*
1193 We ignore error from dd_drop_table() as we anyway
1194 return 'true' failure below.
1195 */
1196
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 bool result = dd::drop_table(thd, db, table_name, *table_def);
1197
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 if (!thd->is_plugin_fake_ddl())
1198
1/2
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
279 (void)trans_intermediate_ddl_commit(thd, result);
1199 }
1200 1018 return true;
1201 } else {
1202
2/4
✓ Branch 0 taken 201012 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 201012 times.
201012 if (compression_dict::cols_table_insert(thd, *table_def)) {
1203 return true;
1204 }
1205 }
1206
1207 /*
1208 If the SE supports atomic DDL, we can use the trx binlog cache.
1209 Otherwise we must use the statement cache.
1210 */
1211
2/2
✓ Branch 0 taken 192739 times.
✓ Branch 1 taken 8273 times.
201012 if (binlog_to_trx_cache != nullptr)
1212 192739 *binlog_to_trx_cache =
1213 192739 (create_info->db_type->flags & HTON_SUPPORTS_ATOMIC_DDL);
1214
1215 201012 return false;
1216 690927 }
1217
1218 /*
1219 SYNOPSIS
1220 write_bin_log()
1221 thd Thread object
1222 clear_error is clear_error to be called
1223 query Query to log
1224 query_length Length of query
1225 is_trans if the event changes either
1226 a trans or non-trans engine.
1227
1228 RETURN VALUES
1229 NONE
1230
1231 DESCRIPTION
1232 Write the binlog if open, routine used in multiple places in this
1233 file
1234 */
1235
1236 898064 int write_bin_log(THD *thd, bool clear_error, const char *query,
1237 size_t query_length, bool is_trans) {
1238 898064 int error = 0;
1239
2/2
✓ Branch 0 taken 337677 times.
✓ Branch 1 taken 560387 times.
898064 if (mysql_bin_log.is_open()) {
1240 337677 int errcode = 0;
1241
2/2
✓ Branch 0 taken 289985 times.
✓ Branch 1 taken 47692 times.
337677 if (clear_error)
1242 289985 thd->clear_error();
1243 else
1244 47692 errcode = query_error_code(thd, true);
1245 337677 error = thd->binlog_query(THD::STMT_QUERY_TYPE, query, query_length,
1246 is_trans, false, false, errcode);
1247 }
1248 898064 return error;
1249 }
1250
1251 252790 bool lock_trigger_names(THD *thd, TABLE_LIST *tables) {
1252
2/2
✓ Branch 0 taken 316606 times.
✓ Branch 1 taken 252790 times.
569396 for (TABLE_LIST *table = tables; table; table = table->next_global) {
1253
3/4
✓ Branch 0 taken 316606 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44229 times.
✓ Branch 3 taken 272377 times.
633212 if (table->open_type == OT_TEMPORARY_ONLY ||
1254
4/4
✓ Branch 0 taken 305504 times.
✓ Branch 1 taken 11102 times.
✓ Branch 2 taken 44229 times.
✓ Branch 3 taken 261275 times.
316606 (table->open_type == OT_TEMPORARY_OR_BASE && is_temporary_table(table)))
1255 57953 continue;
1256
1257
1/2
✓ Branch 0 taken 272377 times.
✗ Branch 1 not taken.
272377 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
1258
1259 272377 const dd::Table *table_obj = nullptr;
1260
4/8
✓ Branch 0 taken 272377 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 272377 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 272377 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 272377 times.
272377 if (thd->dd_client()->acquire(table->db, table->table_name, &table_obj)) {
1261 // Error is reported by the dictionary subsystem.
1262 return true;
1263 }
1264
2/2
✓ Branch 0 taken 13724 times.
✓ Branch 1 taken 258653 times.
272377 if (table_obj == nullptr) continue;
1265
1266
6/10
✓ Branch 0 taken 258653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 258653 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 258653 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1839 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1839 times.
✓ Branch 9 taken 258653 times.
260492 for (const dd::Trigger *trigger : table_obj->triggers()) {
1267
2/4
✓ Branch 0 taken 1839 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1839 times.
1839 if (acquire_exclusive_mdl_for_trigger(thd, table->db,
1268
1/2
✓ Branch 0 taken 1839 times.
✗ Branch 1 not taken.
1839 trigger->name().c_str()))
1269 return true;
1270 }
1271
2/3
✓ Branch 0 taken 258653 times.
✓ Branch 1 taken 13724 times.
✗ Branch 2 not taken.
272377 }
1272
1273 252790 return false;
1274 }
1275
1276 /**
1277 Add MDL requests for specified lock type on all tables referenced by the
1278 given dd::Table object to the list. Also add the referenced table names to
1279 the foreign key invalidator, to be used at a later stage to invalidate the
1280 dd::Table objects.
1281
1282 @param thd Thread handle.
1283 @param table_def dd::Table object.
1284 @param lock_type Type of MDL requests to add.
1285 @param hton Handlerton for table's storage engine.
1286 @param[in,out] mdl_requests List to which MDL requests are to be added.
1287 @param[in,out] fk_invalidator Object keeping track of which dd::Table
1288 objects to invalidate.
1289
1290 @retval operation outcome, false if no error.
1291 */
1292 224376 static bool collect_fk_parents_for_all_fks(
1293 THD *thd, const dd::Table *table_def, handlerton *hton,
1294 enum_mdl_type lock_type, MDL_request_list *mdl_requests,
1295 Foreign_key_parents_invalidator *fk_invalidator) {
1296
6/10
✓ Branch 0 taken 224376 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 224376 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 224376 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1437 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1437 times.
✓ Branch 9 taken 224376 times.
225813 for (const dd::Foreign_key *fk : table_def->foreign_keys()) {
1297 char buff_db[NAME_LEN + 1];
1298 char buff_table[NAME_LEN + 1];
1299
1300
1/2
✓ Branch 0 taken 1437 times.
✗ Branch 1 not taken.
1437 my_stpncpy(buff_db, fk->referenced_table_schema_name().c_str(), NAME_LEN);
1301
1/2
✓ Branch 0 taken 1437 times.
✗ Branch 1 not taken.
1437 my_stpncpy(buff_table, fk->referenced_table_name().c_str(), NAME_LEN);
1302
1303 /*
1304 In lower-case-table-names == 2 mode we store original versions of table
1305 and db names in the data-dictionary. Hence they need to be lowercased
1306 to produce correct MDL key for them and for other uses.
1307 */
1308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1437 times.
1437 if (lower_case_table_names == 2) {
1309 my_casedn_str(system_charset_info, buff_db);
1310 my_casedn_str(system_charset_info, buff_table);
1311 }
1312
1313
1/2
✓ Branch 0 taken 1437 times.
✗ Branch 1 not taken.
1437 MDL_request *mdl_request = new (thd->mem_root) MDL_request;
1314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1437 times.
1437 if (mdl_request == nullptr) return true;
1315
1316
1/2
✓ Branch 0 taken 1437 times.
✗ Branch 1 not taken.
1437 MDL_REQUEST_INIT(mdl_request, MDL_key::TABLE, buff_db, buff_table,
1317 lock_type, MDL_STATEMENT);
1318
1319
1/2
✓ Branch 0 taken 1437 times.
✗ Branch 1 not taken.
1437 mdl_requests->push_front(mdl_request);
1320
1321
1/2
✓ Branch 0 taken 1437 times.
✗ Branch 1 not taken.
1437 mdl_request = new (thd->mem_root) MDL_request;
1322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1437 times.
1437 if (mdl_request == nullptr) return true;
1323
1324
1/2
✓ Branch 0 taken 1437 times.
✗ Branch 1 not taken.
1437 MDL_REQUEST_INIT(mdl_request, MDL_key::SCHEMA, buff_db, "",
1325 MDL_INTENTION_EXCLUSIVE, MDL_STATEMENT);
1326
1327
1/2
✓ Branch 0 taken 1437 times.
✗ Branch 1 not taken.
1437 mdl_requests->push_front(mdl_request);
1328
1329
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 1409 times.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
1437 if (fk_invalidator) fk_invalidator->add(buff_db, buff_table, hton);
1330 }
1331 224376 return false;
1332 }
1333
1334 /**
1335 Add MDL requests for specified lock type on all tables referencing
1336 the given table.
1337
1338 @param thd Thread handle.
1339 @param table_def dd::Table object describing the table.
1340 @param lock_type Type of MDL requests to add.
1341 @param[in,out] mdl_requests List to which MDL requests are to be added.
1342
1343 @retval operation outcome, false if no error.
1344 */
1345 296055 static bool collect_fk_children(THD *thd, const dd::Table *table_def,
1346 enum_mdl_type lock_type,
1347 MDL_request_list *mdl_requests) {
1348
3/4
✓ Branch 0 taken 296055 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 602 times.
✓ Branch 3 taken 296055 times.
296657 for (const dd::Foreign_key_parent *fk : table_def->foreign_key_parents()) {
1349 char buff_db[NAME_LEN + 1];
1350 char buff_table[NAME_LEN + 1];
1351 602 my_stpncpy(buff_db, fk->child_schema_name().c_str(), NAME_LEN);
1352 602 my_stpncpy(buff_table, fk->child_table_name().c_str(), NAME_LEN);
1353
1354 /*
1355 In lower-case-table-names == 2 mode we store original versions of table
1356 and db names in the data-dictionary. Hence they need to be lowercased
1357 to produce correct MDL key for them and for other uses.
1358 */
1359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 602 times.
602 if (lower_case_table_names == 2) {
1360 my_casedn_str(system_charset_info, buff_db);
1361 my_casedn_str(system_charset_info, buff_table);
1362 }
1363
1364
1/2
✓ Branch 0 taken 602 times.
✗ Branch 1 not taken.
602 MDL_request *mdl_request = new (thd->mem_root) MDL_request;
1365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 602 times.
602 if (mdl_request == nullptr) return true;
1366
1367
1/2
✓ Branch 0 taken 602 times.
✗ Branch 1 not taken.
602 MDL_REQUEST_INIT(mdl_request, MDL_key::TABLE, buff_db, buff_table,
1368 lock_type, MDL_STATEMENT);
1369
1370
1/2
✓ Branch 0 taken 602 times.
✗ Branch 1 not taken.
602 mdl_requests->push_front(mdl_request);
1371
1372
1/2
✓ Branch 0 taken 602 times.
✗ Branch 1 not taken.
602 mdl_request = new (thd->mem_root) MDL_request;
1373
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 602 times.
602 if (mdl_request == nullptr) return true;
1374
1375
1/2
✓ Branch 0 taken 602 times.
✗ Branch 1 not taken.
602 MDL_REQUEST_INIT(mdl_request, MDL_key::SCHEMA, buff_db, "",
1376 MDL_INTENTION_EXCLUSIVE, MDL_STATEMENT);
1377
1378
1/2
✓ Branch 0 taken 602 times.
✗ Branch 1 not taken.
602 mdl_requests->push_front(mdl_request);
1379 }
1380
1381 296055 return false;
1382 }
1383
1384 /**
1385 Add MDL requests for exclusive lock on all foreign key names on the given
1386 table to the list.
1387
1388 @param thd Thread context.
1389 @param db Table's schema name.
1390 @param table_def Table definition.
1391 @param[in,out] mdl_requests List to which MDL requests are to be added.
1392
1393 @retval operation outcome, false if no error.
1394 */
1395
1396 133811 static bool collect_fk_names(THD *thd, const char *db,
1397 const dd::Table *table_def,
1398 MDL_request_list *mdl_requests) {
1399
6/10
✓ Branch 0 taken 133811 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 133811 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 133811 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1031 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1031 times.
✓ Branch 9 taken 133811 times.
134842 for (const dd::Foreign_key *fk : table_def->foreign_keys()) {
1400 /*
1401 Since foreign key names are case-insensitive we need to lowercase them
1402 before passing to MDL subsystem.
1403 */
1404 char fk_name[NAME_LEN + 1];
1405
2/4
✓ Branch 0 taken 1031 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1031 times.
✗ Branch 3 not taken.
1031 strmake(fk_name, fk->name().c_str(), NAME_LEN);
1406
1/2
✓ Branch 0 taken 1031 times.
✗ Branch 1 not taken.
1031 my_casedn_str(system_charset_info, fk_name);
1407
1408
1/2
✓ Branch 0 taken 1031 times.
✗ Branch 1 not taken.
1031 MDL_request *mdl_request = new (thd->mem_root) MDL_request;
1409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1031 times.
1031 if (mdl_request == nullptr) return true;
1410
1411
1/2
✓ Branch 0 taken 1031 times.
✗ Branch 1 not taken.
1031 MDL_REQUEST_INIT(mdl_request, MDL_key::FOREIGN_KEY, db, fk_name,
1412 MDL_EXCLUSIVE, MDL_STATEMENT);
1413
1414
1/2
✓ Branch 0 taken 1031 times.
✗ Branch 1 not taken.
1031 mdl_requests->push_front(mdl_request);
1415 }
1416
1417 133811 return false;
1418 }
1419
1420 151509 bool rm_table_do_discovery_and_lock_fk_tables(THD *thd, TABLE_LIST *tables) {
1421 151509 MEM_ROOT mdl_reqs_root(key_memory_rm_db_mdl_reqs_root, MEM_ROOT_BLOCK_SIZE);
1422
1/2
✓ Branch 0 taken 151509 times.
✗ Branch 1 not taken.
151509 MDL_request_list mdl_requests;
1423
1424
2/2
✓ Branch 0 taken 188936 times.
✓ Branch 1 taken 151509 times.
340445 for (TABLE_LIST *table = tables; table; table = table->next_local) {
1425
6/6
✓ Branch 0 taken 177834 times.
✓ Branch 1 taken 11102 times.
✓ Branch 2 taken 43041 times.
✓ Branch 3 taken 134793 times.
✓ Branch 4 taken 43041 times.
✓ Branch 5 taken 145895 times.
201062 if (table->open_type != OT_BASE_ONLY && is_temporary_table(table)) continue;
1426
1427
1/2
✓ Branch 0 taken 145895 times.
✗ Branch 1 not taken.
145895 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
1428
1429 145895 const dd::Abstract_table *abstract_table_def = nullptr;
1430
4/8
✓ Branch 0 taken 145895 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 145895 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 145895 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 145895 times.
145895 if (thd->dd_client()->acquire(table->db, table->table_name,
1431 &abstract_table_def))
1432 return true;
1433
1434
2/2
✓ Branch 0 taken 11259 times.
✓ Branch 1 taken 134636 times.
145895 if (!abstract_table_def) {
1435 /*
1436 If table is missing try to discover it from some storage engine
1437 as it might have foreign keys.
1438 */
1439
1/2
✓ Branch 0 taken 11259 times.
✗ Branch 1 not taken.
11259 int result = ha_create_table_from_engine(
1440 thd, table->db,
1441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11259 times.
11259 (lower_case_table_names == 2) ? table->alias : table->table_name);
1442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11259 times.
11259 if (result > 0) {
1443 // Error during discovery, error should be reported already.
1444 return true;
1445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11259 times.
11259 } else if (result == 0) {
1446 // Table was discovered. Re-try to retrieve its definition.
1447 if (thd->dd_client()->acquire(table->db, table->table_name,
1448 &abstract_table_def))
1449 return true;
1450 } else // result < 0
1451 {
1452 // No table was found.
1453 }
1454 }
1455
1456
4/4
✓ Branch 0 taken 134636 times.
✓ Branch 1 taken 11259 times.
✓ Branch 2 taken 12126 times.
✓ Branch 3 taken 133769 times.
280531 if (!abstract_table_def ||
1457
3/4
✓ Branch 0 taken 134636 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 867 times.
✓ Branch 3 taken 133769 times.
134636 abstract_table_def->type() != dd::enum_table_type::BASE_TABLE)
1458 12126 continue;
1459
1460 const dd::Table *table_def =
1461
1/2
✓ Branch 0 taken 133769 times.
✗ Branch 1 not taken.
133769 dynamic_cast<const dd::Table *>(abstract_table_def);
1462
1463 /*
1464 Ensure that we don't hold memory used by MDL_requests after locks
1465 have been acquired. This reduces memory usage in cases when we have
1466 DROP DATABASE that needs to drop lots of different objects.
1467 */
1468 133769 MEM_ROOT *save_thd_mem_root = thd->mem_root;
1469 auto restore_thd_mem_root =
1470
1/2
✓ Branch 0 taken 133769 times.
✗ Branch 1 not taken.
133769 create_scope_guard([&]() { thd->mem_root = save_thd_mem_root; });
1471 133769 thd->mem_root = &mdl_reqs_root;
1472
1473
2/4
✓ Branch 0 taken 133769 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 133769 times.
133769 if (collect_fk_parents_for_all_fks(thd, table_def, nullptr, MDL_EXCLUSIVE,
1474 &mdl_requests, nullptr))
1475 return true;
1476
1477
2/4
✓ Branch 0 taken 133769 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 133769 times.
133769 if (collect_fk_children(thd, table_def, MDL_EXCLUSIVE, &mdl_requests))
1478 return true;
1479
1480
2/4
✓ Branch 0 taken 133769 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 133769 times.
133769 if (collect_fk_names(thd, table->db, table_def, &mdl_requests)) return true;
1481
3/5
✓ Branch 0 taken 133769 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 133769 times.
✓ Branch 3 taken 12126 times.
✗ Branch 4 not taken.
145895 }
1482
1483
3/4
✓ Branch 0 taken 719 times.
✓ Branch 1 taken 150790 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 151509 times.
152228 if (!mdl_requests.is_empty() &&
1484
2/4
✓ Branch 0 taken 719 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 719 times.
719 thd->mdl_context.acquire_locks(&mdl_requests,
1485 thd->variables.lock_wait_timeout))
1486 return true;
1487
1488 151509 return false;
1489 151509 }
1490
1491 601850 void Foreign_key_parents_invalidator::add(const char *db_name,
1492 const char *table_name,
1493 handlerton *hton) {
1494
1/2
✓ Branch 0 taken 601850 times.
✗ Branch 1 not taken.
601850 m_parent_map.insert(typename Parent_map::value_type(
1495 1203700 typename Parent_map::key_type(db_name, table_name), hton));
1496 601850 }
1497
1498 852138 void Foreign_key_parents_invalidator::invalidate(THD *thd) {
1499
3/4
✓ Branch 0 taken 493422 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 493422 times.
✓ Branch 3 taken 852138 times.
1345560 for (auto parent_it : m_parent_map) {
1500 // Invalidate Table and Table Definition Caches too.
1501
1/2
✓ Branch 0 taken 493422 times.
✗ Branch 1 not taken.
493422 mysql_ha_flush_table(thd, parent_it.first.first.c_str(),
1502 parent_it.first.second.c_str());
1503
1/2
✓ Branch 0 taken 493422 times.
✗ Branch 1 not taken.
493422 close_all_tables_for_name(thd, parent_it.first.first.c_str(),
1504 parent_it.first.second.c_str(), false);
1505
1506 /*
1507 TODO: Should revisit the way we do invalidation to avoid
1508 suppressing errors, which is necessary since it's done after
1509 commit. For now, we use an error handler.
1510 */
1511 493422 Dummy_error_handler error_handler;
1512
1/2
✓ Branch 0 taken 493422 times.
✗ Branch 1 not taken.
493422 thd->push_internal_handler(&error_handler);
1513 bool ignored [[maybe_unused]];
1514
3/6
✓ Branch 0 taken 493422 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 493422 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 493422 times.
✗ Branch 5 not taken.
493422 ignored = thd->dd_client()->invalidate(parent_it.first.first.c_str(),
1515 parent_it.first.second.c_str());
1516
2/6
✓ Branch 0 taken 493422 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 493422 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
493422 DBUG_EXECUTE_IF("fail_while_invalidating_fk_parents",
1517 { my_error(ER_LOCK_DEADLOCK, MYF(0)); });
1518
1/2
✓ Branch 0 taken 493422 times.
✗ Branch 1 not taken.
493422 thd->pop_internal_handler();
1519
1520 // And storage engine internal dictionary cache as well.
1521 #ifdef DISABLED_UNTIL_WL9533
1522 /*
1523 TODO: Simply removing entries from InnoDB internal cache breaks
1524 its FK checking logic at the moment. This is to be solved
1525 as part of WL#9533. We might have to replace invalidation
1526 with cache update to do this.
1527 */
1528 if ((parent_it.second)->dict_cache_reset)
1529 ((parent_it.second))
1530 ->dict_cache_reset(parent_it.first.first.c_str(),
1531 parent_it.first.second.c_str());
1532 #endif
1533 493422 }
1534
1535 852138 m_parent_map.clear();
1536 852138 }
1537
1538 /*
1539 delete (drop) tables.
1540
1541 SYNOPSIS
1542 mysql_rm_table()
1543 thd Thread handle
1544 tables List of tables to delete
1545 if_exists If 1, don't give error if one table doesn't exists
1546
1547 NOTES
1548 Will delete all tables that can be deleted and give a compact error
1549 messages for tables that could not be deleted.
1550 If a table is in use, we will wait for all users to free the table
1551 before dropping it
1552
1553 Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but
1554 not if under LOCK TABLES.
1555
1556 RETURN
1557 false OK. In this case ok packet is sent to user
1558 true Error
1559
1560 */
1561
1562 153362 bool mysql_rm_table(THD *thd, TABLE_LIST *tables, bool if_exists,
1563 bool drop_temporary) {
1564 bool error;
1565 153362 Drop_table_error_handler err_handler;
1566 TABLE_LIST *table;
1567 153363 uint have_non_tmp_table = 0;
1568
1569
1/2
✓ Branch 0 taken 153363 times.
✗ Branch 1 not taken.
153363 DBUG_TRACE;
1570
1571 // DROP table is not allowed in the XA_IDLE or XA_PREPARED transaction states.
1572
3/4
✓ Branch 0 taken 153362 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 153359 times.
153363 if (thd->get_transaction()->xid_state()->check_xa_idle_or_prepared(true)) {
1573 3 return true;
1574 }
1575
1576 /*
1577 DROP tables need to have their logging format determined if
1578 in MIXED mode and dropping a TEMP table.
1579 */
1580
2/4
✓ Branch 0 taken 153360 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 153360 times.
153359 if (thd->decide_logging_format(tables)) {
1581 return true;
1582 }
1583
1584 /* Disable drop of enabled log tables, must be done before name locking */
1585
2/2
✓ Branch 0 taken 185619 times.
✓ Branch 1 taken 153357 times.
338976 for (table = tables; table; table = table->next_local) {
1586
3/4
✓ Branch 0 taken 185618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 185616 times.
185619 if (query_logger.check_if_log_table(table, true)) {
1587
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_BAD_LOG_STATEMENT, MYF(0), "DROP");
1588 2 return true;
1589 }
1590 }
1591
1592
2/2
✓ Branch 0 taken 146114 times.
✓ Branch 1 taken 7243 times.
153357 if (!drop_temporary) {
1593
2/2
✓ Branch 0 taken 146056 times.
✓ Branch 1 taken 58 times.
146114 if (!thd->locked_tables_mode) {
1594
1/2
✓ Branch 0 taken 146057 times.
✗ Branch 1 not taken.
146056 if (lock_table_names(thd, tables, nullptr,
1595
4/4
✓ Branch 0 taken 145978 times.
✓ Branch 1 taken 79 times.
✓ Branch 2 taken 79 times.
✓ Branch 3 taken 145978 times.
292035 thd->variables.lock_wait_timeout, 0) ||
1596
2/4
✓ Branch 0 taken 145978 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 145978 times.
145978 lock_trigger_names(thd, tables))
1597 79 return true;
1598
1599
3/4
✓ Branch 0 taken 145496 times.
✓ Branch 1 taken 482 times.
✓ Branch 2 taken 145496 times.
✗ Branch 3 not taken.
145978 DEBUG_SYNC(thd, "mysql_rm_table_after_lock_table_names");
1600
1601
2/2
✓ Branch 0 taken 177765 times.
✓ Branch 1 taken 145978 times.
323743 for (table = tables; table; table = table->next_local) {
1602
2/2
✓ Branch 0 taken 43035 times.
✓ Branch 1 taken 134730 times.
177765 if (is_temporary_table(table)) continue;
1603
1604 /* Here we are sure that a non-tmp table exists */
1605 134730 have_non_tmp_table = 1;
1606 }
1607 } else {
1608 58 bool acquire_backup_lock = false;
1609
1610
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 47 times.
132 for (table = tables; table; table = table->next_local)
1611
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 79 times.
85 if (is_temporary_table(table)) {
1612 /*
1613 A temporary table.
1614
1615 Don't try to find a corresponding MDL lock or assign it
1616 to table->mdl_request.ticket. There can't be metadata
1617 locks for temporary tables: they are local to the session.
1618
1619 Later in this function we release the MDL lock only if
1620 table->mdl_requeset.ticket is not NULL. Thus here we
1621 ensure that we won't release the metadata lock on the base
1622 table locked with LOCK TABLES as a side effect of temporary
1623 table drop.
1624 */
1625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 assert(table->mdl_request.ticket == nullptr);
1626 } else {
1627 /*
1628 Not a temporary table.
1629
1630 Since 'tables' list can't contain duplicates (this is ensured
1631 by parser) it is safe to cache pointer to the TABLE instances
1632 in its elements.
1633 */
1634
1/2
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
79 table->table = find_table_for_mdl_upgrade(thd, table->db,
1635 table->table_name, false);
1636
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 70 times.
79 if (!table->table) return true;
1637 70 table->mdl_request.ticket = table->table->mdl_ticket;
1638
1639
3/4
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 68 times.
70 if (wait_while_table_is_used(thd, table->table,
1640 HA_EXTRA_FORCE_REOPEN))
1641 2 return true;
1642
1643 /* Here we are sure that a non-tmp table exists */
1644 68 have_non_tmp_table = 1;
1645
1646
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 22 times.
68 if (!acquire_backup_lock) acquire_backup_lock = true;
1647 }
1648
1649
3/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 47 times.
88 if (acquire_backup_lock &&
1650
2/4
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 41 times.
41 acquire_shared_backup_lock(thd, thd->variables.lock_wait_timeout))
1651 return true;
1652 }
1653
1654
2/4
✓ Branch 0 taken 146025 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 146025 times.
146025 if (rm_table_do_discovery_and_lock_fk_tables(thd, tables)) return true;
1655
1656
2/4
✓ Branch 0 taken 146025 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 146025 times.
146025 if (lock_check_constraint_names(thd, tables)) return true;
1657 }
1658
1659 153268 std::vector<MDL_ticket *> safe_to_release_mdl;
1660
1661 {
1662 // This Auto_releaser needs to go out of scope before we start releasing
1663 // metadata locks below. Otherwise we end up having acquired objects for
1664 // which we no longer have any locks held.
1665
1/2
✓ Branch 0 taken 153268 times.
✗ Branch 1 not taken.
153268 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
1666
1667 153268 std::set<handlerton *> post_ddl_htons;
1668 153268 Foreign_key_parents_invalidator fk_invalidator;
1669 bool not_used;
1670
1671 /* mark for close and remove all cached entries */
1672
1/2
✓ Branch 0 taken 153268 times.
✗ Branch 1 not taken.
153268 thd->push_internal_handler(&err_handler);
1673
1/2
✓ Branch 0 taken 153244 times.
✗ Branch 1 not taken.
153268 error = mysql_rm_table_no_locks(thd, tables, if_exists, drop_temporary,
1674 false, &not_used, &post_ddl_htons,
1675 &fk_invalidator, &safe_to_release_mdl);
1676
1/2
✓ Branch 0 taken 153244 times.
✗ Branch 1 not taken.
153244 thd->pop_internal_handler();
1677 153244 }
1678
1679
2/2
✓ Branch 0 taken 146001 times.
✓ Branch 1 taken 7243 times.
153244 if (!drop_temporary) {
1680 /*
1681 Under LOCK TABLES we should release meta-data locks on the tables
1682 which were dropped.
1683
1684 Leave LOCK TABLES mode if we managed to drop all tables which were
1685 locked. Additional check for 'non_temp_tables_count' is to avoid
1686 leaving LOCK TABLES mode if we have dropped only temporary tables.
1687 */
1688
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 145954 times.
146001 if (thd->locked_tables_mode) {
1689 /*
1690 First we need to reopen tables which data-dictionary entries were
1691 updated/invalidated (and thus they were closed) due to fact that
1692 they participate in the same FKs as tables which were dropped.
1693 */
1694
2/4
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 47 times.
47 if (thd->locked_tables_list.reopen_tables(thd)) error = true;
1695
1696
5/6
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 29 times.
✓ Branch 5 taken 4 times.
47 if (thd->lock && thd->lock->table_count == 0 && have_non_tmp_table > 0) {
1697
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 thd->mdl_context.release_statement_locks();
1698
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 thd->locked_tables_list.unlock_locked_tables(thd);
1699 } else {
1700
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 18 times.
30 for (MDL_ticket *mdl_ticket : safe_to_release_mdl) {
1701 /*
1702 Under LOCK TABLES we may have several instances of table open
1703 and locked and therefore have to remove several metadata lock
1704 requests associated with them.
1705 */
1706
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 thd->mdl_context.release_all_locks_for_name(mdl_ticket);
1707 }
1708 }
1709 }
1710 }
1711
1712
2/2
✓ Branch 0 taken 1103 times.
✓ Branch 1 taken 152141 times.
153244 if (error) return true;
1713
1714
6/6
✓ Branch 0 taken 7152 times.
✓ Branch 1 taken 144989 times.
✓ Branch 2 taken 1352 times.
✓ Branch 3 taken 5800 times.
✓ Branch 4 taken 1352 times.
✓ Branch 5 taken 150789 times.
152141 if (thd->lex->drop_temporary && thd->in_multi_stmt_transaction_mode()) {
1715 /*
1716 When autocommit is disabled, dropping temporary table sets this flag
1717 to start transaction in any case (regardless of binlog=on/off,
1718 binlog format and transactional/non-transactional engine) to make
1719 behavior consistent.
1720 */
1721 1352 thd->server_status |= SERVER_STATUS_IN_TRANS;
1722 }
1723
1724
2/2
✓ Branch 0 taken 12068 times.
✓ Branch 1 taken 140073 times.
152141 if (thd->variables.binlog_format == BINLOG_FORMAT_STMT &&
1725
4/4
✓ Branch 0 taken 2209 times.
✓ Branch 1 taken 9859 times.
✓ Branch 2 taken 163 times.
✓ Branch 3 taken 2046 times.
12068 thd->lex->drop_temporary && (thd->in_sub_stmt & SUB_STMT_FUNCTION) &&
1726
1/2
✓ Branch 0 taken 163 times.
✗ Branch 1 not taken.
163 thd->binlog_evt_union.do_union) {
1727 /*
1728 This does not write the query into binary log, it just sets
1729 thd->binlog_evt_union.unioned_events to true for writing
1730 its top function call to the binary log on function exit
1731 in mixed mode and statement mode. So this does not cause
1732 any error.
1733 */
1734
3/6
✓ Branch 0 taken 163 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 163 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 163 times.
✗ Branch 5 not taken.
163 write_bin_log(thd, true, thd->query().str, thd->query().length, true);
1735 }
1736
1737
1/2
✓ Branch 0 taken 152141 times.
✗ Branch 1 not taken.
152141 my_ok(thd);
1738 152141 return false;
1739 153339 }
1740
1741 /**
1742 Runtime context for DROP TABLES statement.
1743 */
1744
1745 class Drop_tables_ctx {
1746 public:
1747 156486 Drop_tables_ctx(bool if_exists_arg, bool drop_temporary_arg,
1748 bool drop_database_arg)
1749 156486 : if_exists(if_exists_arg),
1750 156486 drop_temporary(drop_temporary_arg),
1751 156486 drop_database(drop_database_arg),
1752 156486 base_atomic_tables(PSI_INSTRUMENT_ME),
1753 156486 base_non_atomic_tables(PSI_INSTRUMENT_ME),
1754 156486 tmp_trans_tables(PSI_INSTRUMENT_ME),
1755 156486 tmp_trans_tables_to_binlog(PSI_INSTRUMENT_ME),
1756 156486 tmp_non_trans_tables(PSI_INSTRUMENT_ME),
1757 156486 tmp_non_trans_tables_to_binlog(PSI_INSTRUMENT_ME),
1758 156486 nonexistent_tables(PSI_INSTRUMENT_ME),
1759 156486 views(PSI_INSTRUMENT_ME),
1760 156486 dropped_non_atomic(PSI_INSTRUMENT_ME),
1761 156486 gtid_and_table_groups_state(NO_GTID_MANY_TABLE_GROUPS) {
1762 /* DROP DATABASE implies if_exists and absence of drop_temporary. */
1763
4/6
✓ Branch 0 taken 3218 times.
✓ Branch 1 taken 153268 times.
✓ Branch 2 taken 3218 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3218 times.
✗ Branch 5 not taken.
156486 assert(!drop_database || (if_exists && !drop_temporary));
1764 156486 }
1765
1766 /* Parameters of DROP TABLES statement. */
1767 const bool if_exists;
1768 const bool drop_temporary;
1769 const bool drop_database;
1770
1771 /* Different table groups of tables to be dropped. */
1772 Prealloced_array<TABLE_LIST *, 1> base_atomic_tables;
1773 Prealloced_array<TABLE_LIST *, 1> base_non_atomic_tables;
1774 Prealloced_array<TABLE_LIST *, 1> tmp_trans_tables;
1775 Prealloced_array<TABLE_LIST *, 1> tmp_trans_tables_to_binlog;
1776 Prealloced_array<TABLE_LIST *, 1> tmp_non_trans_tables;
1777 Prealloced_array<TABLE_LIST *, 1> tmp_non_trans_tables_to_binlog;
1778 Prealloced_array<TABLE_LIST *, 1> nonexistent_tables;
1779 Prealloced_array<TABLE_LIST *, 1> views;
1780
1781 /* Methods which simplify checking state of the above groups. */
1782 439486 bool has_base_atomic_tables() const { return base_atomic_tables.size() != 0; }
1783
1784 283606 bool has_base_non_atomic_tables() const {
1785 283606 return base_non_atomic_tables.size() != 0;
1786 }
1787
1788 364596 bool has_tmp_trans_tables() const { return tmp_trans_tables.size() != 0; }
1789
1790 159791 bool has_tmp_trans_tables_to_binlog() const {
1791 159791 return tmp_trans_tables_to_binlog.size() != 0;
1792 }
1793
1794 505489 bool has_tmp_non_trans_tables() const {
1795 505489 return tmp_non_trans_tables.size() != 0;
1796 }
1797
1798 158054 bool has_tmp_non_trans_tables_to_binlog() const {
1799 158054 return tmp_non_trans_tables_to_binlog.size() != 0;
1800 }
1801
1802 156464 bool has_any_nonexistent_tables() const {
1803 156464 return nonexistent_tables.size() != 0;
1804 }
1805 230007 bool has_base_nonexistent_tables() const {
1806
4/4
✓ Branch 0 taken 208674 times.
✓ Branch 1 taken 21333 times.
✓ Branch 2 taken 17083 times.
✓ Branch 3 taken 191591 times.
230007 return !drop_temporary && nonexistent_tables.size() != 0;
1807 }
1808
1809 274102 bool has_tmp_nonexistent_tables() const {
1810
4/4
✓ Branch 0 taken 6641 times.
✓ Branch 1 taken 267461 times.
✓ Branch 2 taken 1492 times.
✓ Branch 3 taken 5149 times.
274102 return drop_temporary && nonexistent_tables.size() != 0;
1811 }
1812
1813 243453 bool has_views() const { return views.size() != 0; }
1814
1815 /**
1816 Base tables in SE which do not support atomic DDL which we managed to
1817 drop so far.
1818 */
1819 Prealloced_array<TABLE_LIST *, 1> dropped_non_atomic;
1820
1821 6 bool has_dropped_non_atomic() const { return dropped_non_atomic.size() != 0; }
1822
1823 /**
1824 In which situation regarding GTID mode and different types
1825 of tables to be dropped we are.
1826
1827 TODO: consider splitting into 2 orthogonal enum/bools.
1828 */
1829 enum {
1830 NO_GTID_MANY_TABLE_GROUPS,
1831 NO_GTID_SINGLE_TABLE_GROUP,
1832 GTID_MANY_TABLE_GROUPS,
1833 GTID_SINGLE_TABLE_GROUP
1834 } gtid_and_table_groups_state;
1835
1836 /* Methods to simplify querying the above state. */
1837 6915 bool has_no_gtid_many_table_groups() const {
1838 6915 return gtid_and_table_groups_state == NO_GTID_MANY_TABLE_GROUPS;
1839 }
1840
1841 107550 bool has_no_gtid_single_table_group() const {
1842 107550 return gtid_and_table_groups_state == NO_GTID_SINGLE_TABLE_GROUP;
1843 }
1844
1845 259108 bool has_gtid_many_table_groups() const {
1846 259108 return gtid_and_table_groups_state == GTID_MANY_TABLE_GROUPS;
1847 }
1848
1849 10223 bool has_gtid_single_table_group() const {
1850 10223 return gtid_and_table_groups_state == GTID_SINGLE_TABLE_GROUP;
1851 }
1852 };
1853
1854 /**
1855 Auxiliary function which appends to the string table identifier with proper
1856 quoting and schema part if necessary.
1857 */
1858
1859 125596 static void append_table_ident(const THD *thd, String *to,
1860 const TABLE_LIST *table, bool force_db) {
1861 // Don't write the database name if it is the current one.
1862
7/8
✓ Branch 0 taken 125198 times.
✓ Branch 1 taken 398 times.
✓ Branch 2 taken 123685 times.
✓ Branch 3 taken 1513 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 123685 times.
✓ Branch 6 taken 1911 times.
✓ Branch 7 taken 123685 times.
125596 if (thd->db().str == nullptr || strcmp(table->db, thd->db().str) != 0 ||
1863 force_db) {
1864 1911 append_identifier(thd, to, table->db, table->db_length, system_charset_info,
1865 thd->charset());
1866
1/2
✓ Branch 0 taken 1911 times.
✗ Branch 1 not taken.
1911 to->append(".");
1867 }
1868 125596 append_identifier(thd, to, table->table_name, table->table_name_length,
1869 system_charset_info, thd->charset());
1870 125596 }
1871
1872 /**
1873 Auxiliary function which appends to the string schema and table name for
1874 the table (without quoting).
1875 */
1876
1877 12130 static void append_table_name(String *to, const TABLE_LIST *table) {
1878
1/2
✓ Branch 0 taken 12130 times.
✗ Branch 1 not taken.
12130 to->append(String(table->db, system_charset_info));
1879 12130 to->append('.');
1880
1/2
✓ Branch 0 taken 12130 times.
✗ Branch 1 not taken.
12130 to->append(String(table->table_name, system_charset_info));
1881 12130 }
1882
1883 /**
1884 Auxiliary class which is used to construct synthesized DROP TABLES
1885 statements for the binary log during execution of DROP TABLES statement.
1886 */
1887
1888 class Drop_tables_query_builder {
1889 public:
1890 108136 Drop_tables_query_builder(THD *thd, bool temporary, bool if_exists,
1891 bool is_trans, bool no_db)
1892 108136 : m_bin_log_is_open(mysql_bin_log.is_open()),
1893 108136 m_thd(thd),
1894 108136 m_is_trans(is_trans),
1895 108136 m_no_db(no_db) {
1896
2/2
✓ Branch 0 taken 98209 times.
✓ Branch 1 taken 9927 times.
108136 if (m_bin_log_is_open) {
1897 98209 m_built_query.set_charset(system_charset_info);
1898
1/2
✓ Branch 0 taken 98209 times.
✗ Branch 1 not taken.
98209 m_built_query.append("DROP ");
1899
3/4
✓ Branch 0 taken 1743 times.
✓ Branch 1 taken 96466 times.
✓ Branch 2 taken 1743 times.
✗ Branch 3 not taken.
98209 if (temporary) m_built_query.append("TEMPORARY ");
1900
1/2
✓ Branch 0 taken 98209 times.
✗ Branch 1 not taken.
98209 m_built_query.append("TABLE ");
1901
3/4
✓ Branch 0 taken 19211 times.
✓ Branch 1 taken 78998 times.
✓ Branch 2 taken 19211 times.
✗ Branch 3 not taken.
98209 if (if_exists) m_built_query.append("IF EXISTS ");
1902 }
1903 108136 }
1904
1905 /*
1906 Constructor for the most common case:
1907 - base tables
1908 - write to binlog trx cache
1909 - Database exists
1910 */
1911 Drop_tables_query_builder(THD *thd, bool if_exists)
1912 : m_bin_log_is_open(mysql_bin_log.is_open()),
1913 m_thd(thd),
1914 m_is_trans(true),
1915 m_no_db(false) {
1916 if (m_bin_log_is_open) {
1917 m_built_query.set_charset(system_charset_info);
1918 m_built_query.append("DROP TABLE ");
1919 if (if_exists) m_built_query.append("IF EXISTS ");
1920 }
1921 }
1922
1923 private:
1924 125596 void add_table_impl(const TABLE_LIST *table) {
1925 125596 append_table_ident(m_thd, &m_built_query, table, m_no_db);
1926
1/2
✓ Branch 0 taken 125596 times.
✗ Branch 1 not taken.
125596 m_built_query.append(",");
1927
1928 125596 m_thd->add_to_binlog_accessed_dbs(table->db);
1929 125596 }
1930
1931 public:
1932 36080 void add_table(const TABLE_LIST *table) {
1933
2/2
✓ Branch 0 taken 26682 times.
✓ Branch 1 taken 9398 times.
36080 if (m_bin_log_is_open) add_table_impl(table);
1934 36080 }
1935
1936 143782 void add_array(const Prealloced_array<TABLE_LIST *, 1> &tables) {
1937
2/2
✓ Branch 0 taken 142726 times.
✓ Branch 1 taken 1056 times.
143782 if (m_bin_log_is_open) {
1938
2/2
✓ Branch 0 taken 98914 times.
✓ Branch 1 taken 142726 times.
241640 for (TABLE_LIST *table : tables) add_table_impl(table);
1939 }
1940 143782 }
1941
1942 94288 bool write_bin_log() {
1943
2/2
✓ Branch 0 taken 84670 times.
✓ Branch 1 taken 9618 times.
94288 if (m_bin_log_is_open) {
1944 /* Chop off the last comma */
1945 84670 m_built_query.chop();
1946
1/2
✓ Branch 0 taken 84670 times.
✗ Branch 1 not taken.
84670 m_built_query.append(" /* generated by server */");
1947
1948 /*
1949 We can't use ::write_bin_log() here as this method is sometimes used
1950 in case when DROP TABLES statement is supposed to report an error.
1951 And ::write_bin_log() either resets error in DA or uses it for binlog
1952 event (which we would like to avoid too).
1953 */
1954
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 84668 times.
84670 if (m_thd->binlog_query(THD::STMT_QUERY_TYPE, m_built_query.ptr(),
1955 84670 m_built_query.length(), m_is_trans,
1956 84670 false /* direct */, m_no_db /* suppress_use */,
1957 0 /* errcode */))
1958 2 return true;
1959 }
1960 94286 return false;
1961 }
1962
1963 private:
1964 bool m_bin_log_is_open;
1965 THD *m_thd;
1966 bool m_is_trans;
1967 bool m_no_db;
1968 String m_built_query;
1969 };
1970
1971 /**
1972 Auxiliary function which prepares for DROP TABLES execution by sorting
1973 tables to be dropped into groups according to their types.
1974 */
1975
1976 156486 static bool rm_table_sort_into_groups(THD *thd, Drop_tables_ctx *drop_ctx,
1977 TABLE_LIST *tables) {
1978 /*
1979 Sort tables into groups according to type of handling they require:
1980
1981 1) Base tables and views. Further divided into the following groups:
1982
1983 a) Base tables in storage engines which don't support atomic DDL.
1984
1985 Their drop can't be rolled back in case of crash or error.
1986 So we drop each such table individually and write to binlog
1987 a single-table DROP TABLE statement corresponding to this
1988 action right after it. This increases chances of SE,
1989 data-dictionary and binary log being in sync if crash occurs.
1990 This also handles case of error/statement being killed in
1991 a natural way - by the time when error occurs we already
1992 have logged all drops which were successful. So we don't
1993 need to write the whole failed statement with error code
1994 to binary log.
1995
1996 b) Base tables in SEs which support atomic DDL.
1997
1998 Their drop can be rolled back, so we drop them in SE, remove
1999 from data-dictionary and write corresponding statement to the
2000 binary log in one atomic transaction all together.
2001
2002 c) Views.
2003
2004 Have to be dropped when this function is called as part of
2005 DROP DATABASE implementation. Dropping them requires
2006 data-dictionary update only, so can be done atomically
2007 with b).
2008
2009 d) Non-existent tables.
2010
2011 In the absence of IF EXISTS clause cause statement failure.
2012 We do this check before dropping any tables to get nice atomic
2013 behavior for most common failure scenario even for tables which
2014 don't support atomic DDL.
2015
2016 When IF EXISTS clause is present notes are generated instead of
2017 error. We assume that non-existing tables support atomic DDL and
2018 write such tables to binary log together with tables from group b)
2019 (after all no-op can be rolled back!) to get a nice single DROP
2020 TABLES statement in the binlog in the default use-case. It is not
2021 a big problem if this assumption turns out to be false on slave.
2022 The statement still will be applied correctly (but crash-safeness
2023 will be sacrificed).
2024
2025 2) Temporary tables.
2026
2027 To avoid problems due to shadowing base tables should be always
2028 binlogged as DROP TEMPORARY TABLE.
2029
2030 Their drop can't be rolled back even for transactional SEs, on the
2031 other hand it can't fail once first simple checks are done. So it
2032 makes sense to drop them after base tables.
2033
2034 Unlike for base tables, it is possible to drop database in which some
2035 connection has temporary tables open. So we can end-up in situation
2036 when connection's default database is no more, but still the connection
2037 has some temporary tables in it. It is possible to drop such tables,
2038 but we should be careful when binlogging such drop.
2039 Using "USE db_which_is_no_more;" before DROP TEMPORARY TABLES will
2040 break replication.
2041
2042 Temporary tables are further divided into the following groups:
2043
2044 a) Temporary tables in non-transactional SE
2045 b) Temporary tables in transactional SE
2046
2047 DROP TEMPORARY TABLES does not commit an ongoing transaction. So in
2048 some circumstances we must binlog changes to non-transactional tables
2049 ahead of transaction, while changes to transactional tables should be
2050 binlogged as part of transaction.
2051
2052 c) Non-existent temporary tables.
2053
2054 Can be non-empty only if DROP TEMPORARY TABLES was used (otherwise
2055 all non-existent tables go to group 1.d)).
2056
2057 Similarly to group 1.d) if IF EXISTS clause is absent causes
2058 statement failure. Otherwise note is generated for each such table.
2059
2060 The non-existing temporary tables are logged together with
2061 transactional ones (group 2.b)), if any transactional tables exist
2062 or if there is only non-existing tables; otherwise are logged
2063 together with non-transactional ones (group 2.a)).
2064
2065 This logic ensures that:
2066 - On master, transactional and non-transactional tables are
2067 written to different statements.
2068 - Therefore, slave will never see statements containing both
2069 transactional and non-transactional temporary tables.
2070 - Since non-existing temporary tables are logged together with
2071 whatever type of temporary tables that exist, the slave thus
2072 writes any statement as just one statement. I.e., the slave
2073 never splits a statement into two. This is crucial when GTIDs
2074 are enabled, since otherwise the statement, which already has
2075 a GTID, would need two different GTIDs.
2076 */
2077
2/2
✓ Branch 0 taken 196612 times.
✓ Branch 1 taken 156480 times.
353092 for (TABLE_LIST *table = tables; table; table = table->next_local) {
2078 /*
2079 Check THD::killed flag, so we can abort potentially lengthy loop.
2080 This can be relevant for DROP DATABASE, for example.
2081 */
2082
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 196607 times.
196613 if (thd->killed) return true;
2083
2084
2/2
✓ Branch 0 taken 185505 times.
✓ Branch 1 taken 11102 times.
196607 if (table->open_type != OT_BASE_ONLY) {
2085 /* DROP DATABASE doesn't deal with temporary tables. */
2086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 185505 times.
185505 assert(!drop_ctx->drop_database);
2087
2088
2/2
✓ Branch 0 taken 135635 times.
✓ Branch 1 taken 49870 times.
185505 if (!is_temporary_table(table)) {
2089 // A temporary table was not found.
2090
2/2
✓ Branch 0 taken 847 times.
✓ Branch 1 taken 134788 times.
135635 if (drop_ctx->drop_temporary) {
2091
1/2
✓ Branch 0 taken 847 times.
✗ Branch 1 not taken.
847 drop_ctx->nonexistent_tables.push_back(table);
2092 50717 continue;
2093 }
2094 /*
2095 Not DROP TEMPORARY and no matching temporary table.
2096 Continue with base tables.
2097 */
2098 } else {
2099 /*
2100 A temporary table was found and can be successfully dropped.
2101
2102 The fact that this temporary table is used by an outer statement
2103 should be detected and reported as error earlier.
2104 */
2105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49870 times.
49870 assert(table->table->query_id == thd->query_id);
2106
2107
2/2
✓ Branch 0 taken 43852 times.
✓ Branch 1 taken 6018 times.
49870 if (table->table->file->has_transactions()) {
2108
1/2
✓ Branch 0 taken 43852 times.
✗ Branch 1 not taken.
43852 drop_ctx->tmp_trans_tables.push_back(table);
2109
3/4
✓ Branch 0 taken 43852 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1092 times.
✓ Branch 3 taken 42760 times.
43852 if (table->table->should_binlog_drop_if_temp())
2110
1/2
✓ Branch 0 taken 1092 times.
✗ Branch 1 not taken.
1092 drop_ctx->tmp_trans_tables_to_binlog.push_back(table);
2111 } else {
2112
1/2
✓ Branch 0 taken 6018 times.
✗ Branch 1 not taken.
6018 drop_ctx->tmp_non_trans_tables.push_back(table);
2113
3/4
✓ Branch 0 taken 6018 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 821 times.
✓ Branch 3 taken 5197 times.
6018 if (table->table->should_binlog_drop_if_temp())
2114
1/2
✓ Branch 0 taken 821 times.
✗ Branch 1 not taken.
821 drop_ctx->tmp_non_trans_tables_to_binlog.push_back(table);
2115 }
2116 49870 continue;
2117 }
2118 }
2119
2120 /* We should not try to drop active log tables. Callers enforce this. */
2121
2/4
✓ Branch 0 taken 145890 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 145890 times.
145890 assert(query_logger.check_if_log_table(table, true) == QUERY_LOG_NONE);
2122
2123
1/2
✓ Branch 0 taken 145890 times.
✗ Branch 1 not taken.
145890 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
2124 145890 const dd::Abstract_table *abstract_table_def = nullptr;
2125
4/8
✓ Branch 0 taken 145890 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 145890 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 145890 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 145890 times.
145890 if (thd->dd_client()->acquire(table->db, table->table_name,
2126 &abstract_table_def)) {
2127 /* Error should have been reported by data-dictionary subsystem. */
2128 return true;
2129 }
2130
2131
2/2
✓ Branch 0 taken 11259 times.
✓ Branch 1 taken 134631 times.
145890 if (!abstract_table_def)
2132
1/2
✓ Branch 0 taken 11259 times.
✗ Branch 1 not taken.
11259 drop_ctx->nonexistent_tables.push_back(table);
2133
3/4
✓ Branch 0 taken 134631 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 133764 times.
✓ Branch 3 taken 867 times.
134631 else if (abstract_table_def->type() == dd::enum_table_type::BASE_TABLE) {
2134 const dd::Table *table_def =
2135
1/2
✓ Branch 0 taken 133764 times.
✗ Branch 1 not taken.
133764 dynamic_cast<const dd::Table *>(abstract_table_def);
2136
2137 133764 handlerton *hton{nullptr};
2138
3/4
✓ Branch 0 taken 133764 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 133763 times.
133764 if (dd::table_storage_engine(thd, table_def, &hton)) return true;
2139
2140 /*
2141 We don't have SEs which support FKs and don't support atomic DDL.
2142 If we ever to support such engines we need to adjust code that checks
2143 if we can drop parent table to correctly handle such SEs.
2144 */
2145
3/4
✓ Branch 0 taken 96469 times.
✓ Branch 1 taken 37294 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 96469 times.
133763 assert(!(hton->flags & HTON_SUPPORTS_FOREIGN_KEYS) ||
2146 (hton->flags & HTON_SUPPORTS_ATOMIC_DDL));
2147
2148
5/6
✓ Branch 0 taken 37294 times.
✓ Branch 1 taken 96469 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 37294 times.
✓ Branch 4 taken 96469 times.
✓ Branch 5 taken 37294 times.
133763 if (hton->flags & HTON_SUPPORTS_ATOMIC_DDL || thd->is_plugin_fake_ddl())
2149
1/2
✓ Branch 0 taken 96469 times.
✗ Branch 1 not taken.
96469 drop_ctx->base_atomic_tables.push_back(table);
2150 else
2151
1/2
✓ Branch 0 taken 37294 times.
✗ Branch 1 not taken.
37294 drop_ctx->base_non_atomic_tables.push_back(table);
2152 } else // View
2153 {
2154
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 861 times.
867 if (!drop_ctx->drop_database) {
2155 /*
2156 Historically, DROP TABLES treats situation when we have a view
2157 instead of table to be dropped as non-existent table.
2158 */
2159
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 drop_ctx->nonexistent_tables.push_back(table);
2160 } else
2161
1/2
✓ Branch 0 taken 861 times.
✗ Branch 1 not taken.
861 drop_ctx->views.push_back(table);
2162 }
2163
2/2
✓ Branch 0 taken 145889 times.
✓ Branch 1 taken 1 times.
145890 }
2164
2165 156480 return false;
2166 }
2167
2168 /**
2169 Auxiliary function which evaluates in which situation DROP TABLES
2170 is regarding GTID and different table groups.
2171 */
2172
2173 156480 static bool rm_table_eval_gtid_and_table_groups_state(
2174 THD *thd, Drop_tables_ctx *drop_ctx) {
2175
2/2
✓ Branch 0 taken 2041 times.
✓ Branch 1 taken 154439 times.
156480 if (thd->variables.gtid_next.type == ASSIGNED_GTID) {
2176 /*
2177 This statement has been assigned GTID.
2178
2179 In this case we need to take special care about group handling
2180 and commits, as statement can't be logged/split into several
2181 statements in this case.
2182
2183 Three different situations are possible in this case:
2184 - "normal" when we have one GTID assigned and one group
2185 to go as single statement to binary logs
2186 - "prohibited" when we have one GTID assigned and two
2187 kinds of temporary tables or mix of temporary and
2188 base tables
2189 - "awkward" when we have one GTID but several groups or
2190 several tables in non-atomic base group (1.a).
2191 */
2192
2193
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1993 times.
2041 if (drop_ctx->drop_database) {
2194 /* DROP DATABASE doesn't drop any temporary tables. */
2195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 assert(!drop_ctx->has_tmp_trans_tables());
2196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 assert(!drop_ctx->has_tmp_non_trans_tables());
2197
2198
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 6 times.
48 if (!drop_ctx->has_base_non_atomic_tables()) {
2199 /*
2200 Normal case. This is DROP DATABASE and we don't have any tables in
2201 SEs which don't support atomic DDL. Remaining tables, views,
2202 routines and events can be dropped atomically and atomically logged
2203 as a single DROP DATABASE statement by the caller.
2204 */
2205 42 drop_ctx->gtid_and_table_groups_state =
2206 Drop_tables_ctx::GTID_SINGLE_TABLE_GROUP;
2207 } else {
2208 /*
2209 Awkward case. We have GTID assigned for DROP DATABASE and it needs
2210 to drop table in SE which doesn't support atomic DDL.
2211
2212 Most probably we are replicating from older (pre-5.8) master or tables
2213 on master and slave have different SEs.
2214 We try to handle situation in the following way - if the whole
2215 statement succeeds caller will log all changes as a single DROP
2216 DATABASE under GTID provided. In case of failure we will emit special
2217 error saying that statement can't be logged correctly and manual
2218 intervention is required.
2219 */
2220 6 drop_ctx->gtid_and_table_groups_state =
2221 Drop_tables_ctx::GTID_MANY_TABLE_GROUPS;
2222 }
2223 } else {
2224 /* Only DROP DATABASE drops views. */
2225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1993 times.
1993 assert(!drop_ctx->has_views());
2226
2227 1993 if ((drop_ctx->has_tmp_trans_tables_to_binlog() &&
2228
6/6
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 1963 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 1987 times.
3984 drop_ctx->has_tmp_non_trans_tables_to_binlog()) ||
2229
2/2
✓ Branch 0 taken 1836 times.
✓ Branch 1 taken 155 times.
1991 ((drop_ctx->has_base_non_atomic_tables() ||
2230
2/2
✓ Branch 0 taken 419 times.
✓ Branch 1 taken 1417 times.
1836 drop_ctx->has_base_atomic_tables() ||
2231
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 399 times.
419 drop_ctx->has_base_nonexistent_tables()) &&
2232
2/2
✓ Branch 0 taken 1589 times.
✓ Branch 1 taken 3 times.
1592 (drop_ctx->has_tmp_trans_tables_to_binlog() ||
2233
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1588 times.
1589 drop_ctx->has_tmp_non_trans_tables_to_binlog()))) {
2234 /*
2235 Prohibited case. We have either both kinds of temporary tables or
2236 mix of non-temporary and temporary tables.
2237
2238 Normally, such DROP TEMPORARY TABLES or DROP TABLES statements are
2239 written into the binary log at least in two pieces. This is, of
2240 course, impossible with a single GTID assigned.
2241
2242 Executing such statements with a GTID assigned is prohibited at
2243 least since 5.7, so should not create new problems with backward
2244 compatibility and cross-version replication.
2245
2246 (Writing deletion of different kinds of temporary and/or base tables
2247 as single multi-table DROP TABLES under single GTID might be
2248 theoretically possible in some cases, but has its own problems).
2249 */
2250 6 my_error(ER_GTID_UNSAFE_BINLOG_SPLITTABLE_STATEMENT_AND_ASSIGNED_GTID,
2251 MYF(0));
2252 6 return true;
2253 }
2254 1987 if (drop_ctx->base_non_atomic_tables.size() == 1 &&
2255
6/6
✓ Branch 0 taken 149 times.
✓ Branch 1 taken 1838 times.
✓ Branch 2 taken 141 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 140 times.
✓ Branch 5 taken 1847 times.
2128 !drop_ctx->has_base_atomic_tables() &&
2256
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 1 times.
141 !drop_ctx->has_base_nonexistent_tables()) {
2257 /*
2258 Normal case. Single base table in SE which don't support atomic DDL
2259 so it will be logged as a single-table DROP TABLES statement.
2260 We still can have temporary tables in this drop, but only those ones
2261 which are not logged (previous 'if' would detect them).
2262 Such temporary tables will be just dropped, but not logged.
2263 */
2264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 assert(!drop_ctx->has_tmp_trans_tables_to_binlog());
2265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 assert(!drop_ctx->has_tmp_non_trans_tables_to_binlog());
2266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 assert(!drop_ctx->has_tmp_nonexistent_tables());
2267 140 drop_ctx->gtid_and_table_groups_state =
2268 Drop_tables_ctx::GTID_SINGLE_TABLE_GROUP;
2269 1847 } else if ((drop_ctx->has_base_atomic_tables() ||
2270
6/6
✓ Branch 0 taken 421 times.
✓ Branch 1 taken 1426 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 400 times.
✓ Branch 4 taken 1435 times.
✓ Branch 5 taken 412 times.
3294 drop_ctx->has_base_nonexistent_tables()) &&
2271
2/2
✓ Branch 0 taken 1435 times.
✓ Branch 1 taken 12 times.
1447 !drop_ctx->has_base_non_atomic_tables()) {
2272 /*
2273 Normal case. Several base tables which can be dropped atomically.
2274 Can be logged as one atomic multi-table DROP TABLES statement.
2275 Other groups are empty.
2276 */
2277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1435 times.
1435 assert(!drop_ctx->has_tmp_trans_tables_to_binlog());
2278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1435 times.
1435 assert(!drop_ctx->has_tmp_non_trans_tables_to_binlog());
2279 1435 drop_ctx->gtid_and_table_groups_state =
2280 Drop_tables_ctx::GTID_SINGLE_TABLE_GROUP;
2281
4/4
✓ Branch 0 taken 215 times.
✓ Branch 1 taken 197 times.
✓ Branch 2 taken 229 times.
✓ Branch 3 taken 183 times.
627 } else if (drop_ctx->has_tmp_trans_tables() ||
2282
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 170 times.
215 (!drop_ctx->has_tmp_non_trans_tables() &&
2283
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 13 times.
45 drop_ctx->has_tmp_nonexistent_tables())) {
2284 /*
2285 Normal case. Some temporary transactional tables (and/or possibly
2286 some non-existent temporary tables) to be logged as one multi-table
2287 DROP TEMPORARY TABLES statement.
2288 Other groups are empty.
2289 */
2290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 229 times.
229 assert(!drop_ctx->has_base_non_atomic_tables());
2291
2/4
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 229 times.
✗ Branch 3 not taken.
229 assert(!drop_ctx->has_base_atomic_tables() &&
2292 !drop_ctx->has_base_nonexistent_tables());
2293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 229 times.
229 assert(!drop_ctx->has_tmp_non_trans_tables_to_binlog());
2294 229 drop_ctx->gtid_and_table_groups_state =
2295 Drop_tables_ctx::GTID_SINGLE_TABLE_GROUP;
2296
2/2
✓ Branch 0 taken 170 times.
✓ Branch 1 taken 13 times.
183 } else if (drop_ctx->has_tmp_non_trans_tables()) {
2297 /*
2298 Normal case. Some temporary non-transactional tables (and possibly
2299 some non-existent temporary tables) to be logged as one multi-table
2300 DROP TEMPORARY TABLES statement.
2301 Other groups are empty.
2302 */
2303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
170 assert(!drop_ctx->has_base_non_atomic_tables());
2304
2/4
✓ Branch 0 taken 170 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 170 times.
✗ Branch 3 not taken.
170 assert(!drop_ctx->has_base_atomic_tables() &&
2305 !drop_ctx->has_base_nonexistent_tables());
2306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170 times.
170 assert(!drop_ctx->has_tmp_trans_tables());
2307 170 drop_ctx->gtid_and_table_groups_state =
2308 Drop_tables_ctx::GTID_SINGLE_TABLE_GROUP;
2309 } else {
2310 /*
2311 Awkward case. We have several tables from non-atomic group 1.a, or
2312 tables from both atomic (1.b, 1.c, 1.d) and non-atomic groups.
2313
2314 Most probably we are replicating from older (pre-5.8) master or tables
2315 on master and slave have different SEs.
2316 We try to handle this situation gracefully by writing single
2317 multi-table DROP TABLES statement including tables from all groups
2318 under GTID provided. Of course this means that we are not crash-safe
2319 in this case. But we can't be fully crash-safe in cases when
2320 non-atomic tables are involved anyway.
2321
2322 Note that temporary tables groups still should be empty in this case.
2323 */
2324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 assert(!drop_ctx->has_tmp_trans_tables());
2325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 assert(!drop_ctx->has_tmp_non_trans_tables());
2326 13 drop_ctx->gtid_and_table_groups_state =
2327 Drop_tables_ctx::GTID_MANY_TABLE_GROUPS;
2328 }
2329 }
2330 } else {
2331 /*
2332 This statement has no GTID assigned. We can handle any mix of
2333 groups in this case. However full atomicity is guaranteed only
2334 in certain scenarios.
2335 */
2336
2337
2/2
✓ Branch 0 taken 3170 times.
✓ Branch 1 taken 151269 times.
154439 if (drop_ctx->drop_database) {
2338 /* DROP DATABASE doesn't drop any temporary tables. */
2339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3170 times.
3170 assert(!drop_ctx->has_tmp_trans_tables());
2340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3170 times.
3170 assert(!drop_ctx->has_tmp_non_trans_tables());
2341
2342
2/2
✓ Branch 0 taken 2741 times.
✓ Branch 1 taken 429 times.
3170 if (!drop_ctx->has_base_non_atomic_tables()) {
2343 /*
2344 Fully atomic case. This is DROP DATABASE and we don't have any
2345 tables in SEs which don't support atomic DDL. Remaining tables,
2346 views, routines and events can be dropped atomically and atomically
2347 logged as a single DROP DATABASE statement by the caller.
2348 */
2349 2741 drop_ctx->gtid_and_table_groups_state =
2350 Drop_tables_ctx::NO_GTID_SINGLE_TABLE_GROUP;
2351 } else {
2352 /*
2353 Non-atomic case. This is DROP DATABASE which needs to drop some
2354 tables in SE which doesn't support atomic DDL. To improve
2355 crash-safety we log separate DROP TABLE IF EXISTS for each such
2356 table dropped. Remaining tables, views, routines and events are
2357 dropped atomically and atomically logged as a single DROP DATABASE
2358 statement by the caller.
2359 */
2360 429 drop_ctx->gtid_and_table_groups_state =
2361 Drop_tables_ctx::NO_GTID_MANY_TABLE_GROUPS;
2362 }
2363 } else {
2364 /* Only DROP DATABASE drops views. */
2365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 151269 times.
151269 assert(!drop_ctx->has_views());
2366
2367 151269 if (drop_ctx->base_non_atomic_tables.size() == 1 &&
2368
2/2
✓ Branch 0 taken 31567 times.
✓ Branch 1 taken 176 times.
31743 !drop_ctx->has_base_atomic_tables() &&
2369
2/2
✓ Branch 0 taken 31494 times.
✓ Branch 1 taken 73 times.
31567 !drop_ctx->has_base_nonexistent_tables() &&
2370
6/6
✓ Branch 0 taken 31743 times.
✓ Branch 1 taken 119526 times.
✓ Branch 2 taken 31485 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 31480 times.
✓ Branch 5 taken 119789 times.
214497 !drop_ctx->has_tmp_trans_tables() &&
2371
2/2
✓ Branch 0 taken 31480 times.
✓ Branch 1 taken 5 times.
31485 !drop_ctx->has_tmp_non_trans_tables()) {
2372 /*
2373 Simple non-atomic case. Single base table in SE which don't
2374 support atomic DDL so it will be logged as a single-table
2375 DROP TABLES statement. Other groups are empty.
2376 */
2377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31480 times.
31480 assert(!drop_ctx->has_tmp_nonexistent_tables());
2378 31480 drop_ctx->gtid_and_table_groups_state =
2379 Drop_tables_ctx::NO_GTID_SINGLE_TABLE_GROUP;
2380 119789 } else if ((drop_ctx->has_base_atomic_tables() ||
2381
2/2
✓ Branch 0 taken 8941 times.
✓ Branch 1 taken 49935 times.
58876 drop_ctx->has_base_nonexistent_tables()) &&
2382
2/2
✓ Branch 0 taken 69245 times.
✓ Branch 1 taken 609 times.
69854 !drop_ctx->has_base_non_atomic_tables() &&
2383
6/6
✓ Branch 0 taken 58876 times.
✓ Branch 1 taken 60913 times.
✓ Branch 2 taken 68570 times.
✓ Branch 3 taken 675 times.
✓ Branch 4 taken 68561 times.
✓ Branch 5 taken 51228 times.
308148 !drop_ctx->has_tmp_trans_tables() &&
2384
2/2
✓ Branch 0 taken 68561 times.
✓ Branch 1 taken 9 times.
68570 !drop_ctx->has_tmp_non_trans_tables()) {
2385 /*
2386 Fully atomic case. Several base tables which can be dropped
2387 atomically. Can be logged as one atomic multi-table DROP TABLES
2388 statement. Other groups are empty.
2389 */
2390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 68561 times.
68561 assert(!drop_ctx->has_tmp_nonexistent_tables());
2391 68561 drop_ctx->gtid_and_table_groups_state =
2392 Drop_tables_ctx::NO_GTID_SINGLE_TABLE_GROUP;
2393 51228 } else if (!drop_ctx->has_base_non_atomic_tables() &&
2394
6/6
✓ Branch 0 taken 49422 times.
✓ Branch 1 taken 1806 times.
✓ Branch 2 taken 48738 times.
✓ Branch 3 taken 684 times.
✓ Branch 4 taken 48738 times.
✓ Branch 5 taken 2490 times.
99966 !drop_ctx->has_base_atomic_tables() &&
2395
1/2
✓ Branch 0 taken 48738 times.
✗ Branch 1 not taken.
48738 !drop_ctx->has_base_nonexistent_tables()) {
2396 /* No base tables to be dropped. */
2397
4/4
✓ Branch 0 taken 42781 times.
✓ Branch 1 taken 5957 times.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 48703 times.
91519 if (drop_ctx->has_tmp_trans_tables() &&
2398
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 42746 times.
42781 drop_ctx->has_tmp_non_trans_tables()) {
2399 /*
2400 Complex case with temporary tables. We have both transactional
2401 and non-transactional temporary tables and no base tables at all.
2402
2403 We will log separate DROP TEMPORARY TABLES statements for each of
2404 two groups.
2405 */
2406 35 drop_ctx->gtid_and_table_groups_state =
2407 Drop_tables_ctx::NO_GTID_MANY_TABLE_GROUPS;
2408 } else {
2409 /*
2410 Simple case with temporary tables. We have either only
2411 transactional or non-transactional temporary tables.
2412 Possibly some non-existent temporary tables.
2413
2414 We can log our statement as a single DROP TEMPORARY TABLES
2415 statement.
2416 */
2417
9/14
✓ Branch 0 taken 42746 times.
✓ Branch 1 taken 5957 times.
✓ Branch 2 taken 42746 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5957 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5247 times.
✓ Branch 7 taken 710 times.
✓ Branch 8 taken 710 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 710 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 710 times.
✗ Branch 13 not taken.
48703 assert((drop_ctx->has_tmp_trans_tables() &&
2418 !drop_ctx->has_tmp_non_trans_tables()) ||
2419 (!drop_ctx->has_tmp_trans_tables() &&
2420 drop_ctx->has_tmp_non_trans_tables()) ||
2421 (!drop_ctx->has_tmp_trans_tables() &&
2422 !drop_ctx->has_tmp_non_trans_tables() &&
2423 drop_ctx->has_tmp_nonexistent_tables()));
2424 48703 drop_ctx->gtid_and_table_groups_state =
2425 Drop_tables_ctx::NO_GTID_SINGLE_TABLE_GROUP;
2426 }
2427 } else {
2428 /*
2429 Complex non-atomic case. We have several tables from non-atomic
2430 group 1.a, or tables from both atomic (1.b, 1.c, 1.d) and non-atomic
2431 groups, or mix of base and temporary tables.
2432
2433 Our statement will be written to binary log as several DROP TABLES and
2434 DROP TEMPORARY TABLES statements.
2435 */
2436 2490 drop_ctx->gtid_and_table_groups_state =
2437 Drop_tables_ctx::NO_GTID_MANY_TABLE_GROUPS;
2438 }
2439 }
2440 }
2441
2442 156474 return false;
2443 }
2444
2445 /**
2446 Check if DROP TABLES or DROP DATABASE statement going to violate
2447 some foreign key constraint by dropping its parent table without
2448 dropping child at the same time.
2449 */
2450 155436 static bool rm_table_check_fks(THD *thd, Drop_tables_ctx *drop_ctx) {
2451 /*
2452 In FOREIGN_KEY_CHECKS=0 mode it is allowed to drop parent without
2453 dropping child at the same time, so we return early.
2454 In FOREIGN_KEY_CHECKS=1 mode we need to check if we are about to
2455 drop parent table without dropping child table.
2456 */
2457
2/2
✓ Branch 0 taken 1363 times.
✓ Branch 1 taken 154073 times.
155436 if (thd->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS) return false;
2458
2459 // Earlier we assert that only SEs supporting atomic DDL support FKs.
2460
2/2
✓ Branch 0 taken 95432 times.
✓ Branch 1 taken 154057 times.
249489 for (TABLE_LIST *table : drop_ctx->base_atomic_tables) {
2461
1/2
✓ Branch 0 taken 95432 times.
✗ Branch 1 not taken.
95432 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
2462 95432 const dd::Table *table_def = nullptr;
2463
4/8
✓ Branch 0 taken 95432 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95432 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 95432 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 95432 times.
95432 if (thd->dd_client()->acquire(table->db, table->table_name, &table_def))
2464 return true;
2465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95432 times.
95432 assert(table_def != nullptr);
2466
2467
6/8
✓ Branch 0 taken 95432 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95432 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 95431 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 95431 times.
95432 if (table_def && table_def->hidden() == dd::Abstract_table::HT_HIDDEN_SE) {
2468
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_NO_SUCH_TABLE, MYF(0), table->db, table->table_name);
2469 assert(true);
2470 1 return true;
2471 }
2472
2473
3/4
✓ Branch 0 taken 95431 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 342 times.
✓ Branch 3 taken 95416 times.
95758 for (const dd::Foreign_key_parent *fk : table_def->foreign_key_parents()) {
2474
2/2
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 237 times.
342 if (drop_ctx->drop_database) {
2475 /*
2476 In case of DROP DATABASE list of tables to be dropped can be huge.
2477 We avoid scanning it by assuming that DROP DATABASE will drop all
2478 tables in the database and no tables from other databases.
2479 */
2480
1/2
✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
105 if (my_strcasecmp(table_alias_charset, fk->child_schema_name().c_str(),
2481
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 101 times.
105 table->db) != 0) {
2482
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
8 my_error(ER_FK_CANNOT_DROP_PARENT, MYF(0), table->table_name,
2483 8 fk->fk_name().c_str(), fk->child_table_name().c_str());
2484 15 return true;
2485 }
2486 } else {
2487
1/2
✓ Branch 0 taken 237 times.
✗ Branch 1 not taken.
237 if (my_strcasecmp(table_alias_charset, fk->child_schema_name().c_str(),
2488
3/4
✓ Branch 0 taken 237 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 217 times.
474 table->db) == 0 &&
2489
3/4
✓ Branch 0 taken 237 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 217 times.
237 my_strcasecmp(table_alias_charset, fk->child_table_name().c_str(),
2490 table->table_name) == 0)
2491 20 continue;
2492
2493 217 bool child_dropped = false;
2494
2495
4/6
✓ Branch 0 taken 217 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 217 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 307 times.
✓ Branch 5 taken 11 times.
318 for (TABLE_LIST *dropped : drop_ctx->base_atomic_tables) {
2496
1/2
✓ Branch 0 taken 307 times.
✗ Branch 1 not taken.
307 if (my_strcasecmp(table_alias_charset,
2497 fk->child_schema_name().c_str(),
2498
3/4
✓ Branch 0 taken 307 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 206 times.
✓ Branch 3 taken 101 times.
614 dropped->db) == 0 &&
2499
3/4
✓ Branch 0 taken 307 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 206 times.
✓ Branch 3 taken 101 times.
307 my_strcasecmp(table_alias_charset, fk->child_table_name().c_str(),
2500 dropped->table_name) == 0) {
2501 206 child_dropped = true;
2502 206 break;
2503 }
2504 }
2505
2506
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 206 times.
217 if (!child_dropped) {
2507
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
22 my_error(ER_FK_CANNOT_DROP_PARENT, MYF(0), table->table_name,
2508 22 fk->fk_name().c_str(), fk->child_table_name().c_str());
2509 11 return true;
2510 }
2511 }
2512 }
2513
2/2
✓ Branch 0 taken 95416 times.
✓ Branch 1 taken 16 times.
95432 }
2514
2515 154057 return false;
2516 }
2517
2518 /**
2519 Update the unique constraint names for FKs which reference table
2520 being dropped.
2521
2522 @param thd Thread handle.
2523 @param parent_table_db Schema name for table being dropped.
2524 @param parent_table_name Name of the table being dropped.
2525 @param parent_table_def dd::Table object representing the dropped table.
2526 @param hton Handlerton for table's storage engine.
2527
2528 @retval operation outcome, false if no error.
2529 */
2530 133691 static bool adjust_fk_children_for_parent_drop(
2531 THD *thd, const char *parent_table_db, const char *parent_table_name,
2532 const dd::Table *parent_table_def, handlerton *hton [[maybe_unused]]) {
2533 133691 for (const dd::Foreign_key_parent *parent_fk :
2534
3/4
✓ Branch 0 taken 133691 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 365 times.
✓ Branch 3 taken 133691 times.
267747 parent_table_def->foreign_key_parents()) {
2535
1/2
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
365 if (my_strcasecmp(table_alias_charset,
2536 parent_fk->child_schema_name().c_str(),
2537
3/4
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 336 times.
730 parent_table_db) == 0 &&
2538
3/4
✓ Branch 0 taken 365 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 336 times.
365 my_strcasecmp(table_alias_charset,
2539 parent_fk->child_table_name().c_str(),
2540 parent_table_name) == 0)
2541 274 continue;
2542
2543 336 dd::Table *child_table_def = nullptr;
2544
2545
4/8
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 336 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 336 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 336 times.
1008 if (thd->dd_client()->acquire_for_modification(
2546 336 parent_fk->child_schema_name().c_str(),
2547 336 parent_fk->child_table_name().c_str(), &child_table_def))
2548 return true;
2549
2550
2/2
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 91 times.
336 if (child_table_def == nullptr) continue;
2551
2552
6/10
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 91 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 126 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 126 times.
✓ Branch 9 taken 91 times.
217 for (dd::Foreign_key *fk : *(child_table_def->foreign_keys())) {
2553
2/4
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
126 if (my_strcasecmp(table_alias_charset,
2554 fk->referenced_table_schema_name().c_str(),
2555
3/4
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91 times.
✓ Branch 3 taken 35 times.
252 parent_table_db) == 0 &&
2556
4/6
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 91 times.
✓ Branch 5 taken 35 times.
126 my_strcasecmp(table_alias_charset,
2557 fk->referenced_table_name().c_str(),
2558 parent_table_name) == 0) {
2559 // Note: Setting "" is interpreted as NULL.
2560
2/4
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91 times.
✗ Branch 3 not taken.
91 fk->set_unique_constraint_name("");
2561 }
2562 }
2563
2564
2/4
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 91 times.
91 if (thd->dd_client()->update(child_table_def)) return true;
2565
2566 char buff_db[NAME_LEN + 1];
2567 char buff_table[NAME_LEN + 1];
2568
2569 91 my_stpncpy(buff_db, parent_fk->child_schema_name().c_str(), NAME_LEN);
2570 91 my_stpncpy(buff_table, parent_fk->child_table_name().c_str(), NAME_LEN);
2571
2572 /*
2573 In lower-case-table-names == 2 mode we store original versions of
2574 table and db names in the data-dictionary. Hence they need to be
2575 lowercased to be used with Table and Table Definition Caches.
2576 */
2577
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
91 if (lower_case_table_names == 2) {
2578 my_casedn_str(system_charset_info, buff_db);
2579 my_casedn_str(system_charset_info, buff_table);
2580 }
2581
2582
1/2
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
91 mysql_ha_flush_table(thd, buff_db, buff_table);
2583
1/2
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
91 close_all_tables_for_name(thd, buff_db, buff_table, false);
2584
2585 #ifdef DISABLED_UNTIL_WL9533
2586 /*
2587 TODO: Simply removing entries from InnoDB internal cache breaks
2588 its FK checking logic at the moment. This is to be solved
2589 as part of WL#9533. We might have to replace invalidation
2590 with cache update to do this.Also we might have to postpone
2591 such invalidation/update until statement commit time.
2592 */
2593 if (hton->dict_cache_reset)
2594 hton->dict_cache_reset(parent_fk->child_schema_name().c_str(),
2595 parent_fk->child_table_name().c_str());
2596 #endif
2597 }
2598
2599 133691 return false;
2600 }
2601
2602 /**
2603 * Validates the ALTER TABLE command with respect to any secondary engine
2604 * operations.
2605 *
2606 * @param alter_info Alter table operations.
2607 * @param create_info Table option changes.
2608 * @param table The table that is being altered.
2609 *
2610 * @return True if invalid, false otherwise.
2611 */
2612 91860 static bool validate_secondary_engine_option(const Alter_info &alter_info,
2613 const HA_CREATE_INFO &create_info,
2614 const TABLE &table) {
2615 // Validation necessary only for tables with a secondary engine defined.
2616
2/2
✓ Branch 0 taken 91822 times.
✓ Branch 1 taken 38 times.
91860 if (!table.s->has_secondary_engine()) return false;
2617
2618 // Changing table option is the only valid ALTER TABLE operation.
2619 38 constexpr uint64_t supported_alter_operations = Alter_info::ALTER_OPTIONS;
2620
2621 // The only table option that may be changed is SECONDARY_ENGINE.
2622 38 constexpr uint64_t supported_table_options = HA_CREATE_USED_SECONDARY_ENGINE;
2623
2624
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 5 times.
38 if (alter_info.flags & ~supported_alter_operations ||
2625
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 29 times.
33 create_info.used_fields & ~supported_table_options) {
2626 9 my_error(ER_SECONDARY_ENGINE_DDL, MYF(0));
2627 9 return true;
2628 }
2629
2630 // Secondary engine of a table must be set to NULL before it can be redefined.
2631
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 28 times.
29 if (create_info.secondary_engine.str != nullptr) {
2632 1 my_error(ER_SECONDARY_ENGINE, MYF(0),
2633 "Table already has a secondary engine defined");
2634 1 return true;
2635 }
2636
2637 28 return false;
2638 }
2639
2640 /**
2641 * Loads a table from its primary engine into its secondary engine.
2642 *
2643 * This call assumes that MDL_SHARED_NO_WRITE/SECLOAD_SCAN_START_MDL lock
2644 * on the table have been acquired by caller. During its execution it may
2645 * downgrade this lock to MDL_SHARED_UPGRADEABLE/SECLOAD_PAR_SCAN_MDL.
2646 *
2647 * @param thd Thread handler.
2648 * @param table Table in primary storage engine.
2649 *
2650 * @return True if error, false otherwise.
2651 */
2652 91 static bool secondary_engine_load_table(THD *thd, const TABLE &table) {
2653
2/4
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 91 times.
91 assert(thd->mdl_context.owns_equal_or_stronger_lock(
2654 MDL_key::TABLE, table.s->db.str, table.s->table_name.str,
2655 SECLOAD_SCAN_START_MDL));
2656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
91 assert(table.s->has_secondary_engine());
2657
2658 // At least one column must be loaded into the secondary engine.
2659
3/4
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 89 times.
91 if (bitmap_bits_set(table.read_set) == 0) {
2660
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_SECONDARY_ENGINE, MYF(0),
2661 "All columns marked as NOT SECONDARY");
2662 2 return true;
2663 }
2664
2665 // The defined secondary engine must be the name of a valid storage engine.
2666 plugin_ref plugin =
2667
1/2
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
89 ha_resolve_by_name(thd, &table.s->secondary_engine, false);
2668
6/8
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 88 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 88 times.
89 if ((plugin == nullptr) || !plugin_is_ready(table.s->secondary_engine,
2669 MYSQL_STORAGE_ENGINE_PLUGIN)) {
2670
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), table.s->secondary_engine.str);
2671 1 return true;
2672 }
2673
2674 // The engine must support being used as a secondary engine.
2675 88 handlerton *hton = plugin_data<handlerton *>(plugin);
2676
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 87 times.
88 if (!(hton->flags & HTON_IS_SECONDARY_ENGINE)) {
2677
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SECONDARY_ENGINE, MYF(0),
2678 "Unsupported secondary storage engine");
2679 1 return true;
2680 }
2681
2682 // Get handler to the secondary engine into which the table will be loaded.
2683 87 const bool is_partitioned = table.s->m_part_info != nullptr;
2684 unique_ptr_destroy_only<handler> handler(
2685
1/2
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
87 get_new_handler(table.s, is_partitioned, thd->mem_root, hton));
2686
2687 // Load table from primary into secondary engine and add to change
2688 // propagation if that is enabled.
2689
1/2
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
87 return handler->ha_load_table(table);
2690 87 }
2691
2692 /**
2693 * Unloads a table from its secondary engine.
2694 *
2695 * @note An MDL_EXCLUSIVE or stronger lock on the table must have been acquired
2696 * prior to calling this function to ensure that queries already offloaded to
2697 * the secondary engine finished execution before unloading the table.
2698 *
2699 * @param thd Thread handler.
2700 * @param db_name Database name.
2701 * @param table_name Table name.
2702 * @param table_def Table definition.
2703 * @param error_if_not_loaded If true and the table is not loaded in the
2704 * secondary engine, this function will return an
2705 * error. If false, this function will not return an
2706 * error if the table is not loaded in the secondary
2707 * engine.
2708 *
2709 * @return True if error, false otherwise.
2710 */
2711 133772 static bool secondary_engine_unload_table(THD *thd, const char *db_name,
2712 const char *table_name,
2713 const dd::Table &table_def,
2714 bool error_if_not_loaded) {
2715
2/4
✓ Branch 0 taken 133772 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 133772 times.
133772 assert(thd->mdl_context.owns_equal_or_stronger_lock(
2716 MDL_key::TABLE, db_name, table_name, MDL_EXCLUSIVE));
2717
2718 // Nothing to unload if table has no secondary engine defined.
2719 LEX_CSTRING secondary_engine;
2720
7/12
✓ Branch 0 taken 133772 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 133772 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 133772 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 150 times.
✓ Branch 7 taken 133622 times.
✓ Branch 8 taken 133622 times.
✓ Branch 9 taken 150 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
267694 if (!table_def.options().exists("secondary_engine") ||
2721
7/14
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 150 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 150 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 150 times.
✓ Branch 8 taken 150 times.
✓ Branch 9 taken 133622 times.
✓ Branch 10 taken 133772 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
133922 table_def.options().get("secondary_engine", &secondary_engine,
2722 thd->mem_root))
2723 133622 return false;
2724
2725 // Get handlerton of secondary engine. It may happen that no handlerton is
2726 // found either if the defined secondary engine is invalid (if so, the table
2727 // was never loaded either) or if the secondary engine has been uninstalled
2728 // after tables were loaded into it (in which case the tables have already
2729 // been unloaded).
2730
1/2
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
150 plugin_ref plugin = ha_resolve_by_name(thd, &secondary_engine, false);
2731
4/4
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 117 times.
267 if ((plugin == nullptr) ||
2732
2/4
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 117 times.
117 !plugin_is_ready(secondary_engine, MYSQL_STORAGE_ENGINE_PLUGIN)) {
2733
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (error_if_not_loaded)
2734 my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), secondary_engine);
2735 33 return error_if_not_loaded;
2736 }
2737 117 handlerton *hton = plugin_data<handlerton *>(plugin);
2738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117 times.
117 if (hton == nullptr) {
2739 if (error_if_not_loaded)
2740 my_error(ER_SECONDARY_ENGINE, MYF(0),
2741 "Table is not loaded on a secondary engine");
2742 return error_if_not_loaded;
2743 }
2744
2745 // The defined secondary engine is a valid storage engine. However, if the
2746 // engine is not a valid secondary engine, no tables have been loaded and
2747 // there is nothing to be done.
2748
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 112 times.
117 if (!(hton->flags & HTON_IS_SECONDARY_ENGINE)) return false;
2749
2750 // Get handler for table in secondary engine.
2751
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
112 const bool is_partitioned = table_def.partition_type() != dd::Table::PT_NONE;
2752 unique_ptr_destroy_only<handler> handler(
2753
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
112 get_new_handler(nullptr, is_partitioned, thd->mem_root, hton));
2754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
112 if (handler == nullptr) return true;
2755
2756 // Unload table from secondary engine.
2757
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
112 return handler->ha_unload_table(db_name, table_name, error_if_not_loaded) > 0;
2758 112 }
2759
2760 /**
2761 Auxiliary function which drops single base table.
2762
2763 @param thd Thread handler.
2764 @param drop_ctx DROP TABLES runtime context.
2765 @param table Table to drop.
2766 @param atomic Indicates whether table to be dropped is in SE
2767 which supports atomic DDL, so changes to the
2768 data-dictionary should not be committed.
2769 @param[in,out] post_ddl_htons Set of handlertons for tables in SEs supporting
2770 atomic DDL for which post-DDL hook needs to
2771 be called after statement commit or rollback.
2772 @param[in,out] fk_invalidator Object keeping track of which dd::Table
2773 objects need to be invalidated since the
2774 correspond to the parent tables for FKs
2775 on a table being dropped.
2776 @param[in,out] safe_to_release_mdl Under LOCK TABLES set of metadata locks
2777 on tables dropped which is safe to
2778 release after DROP operation.
2779 @param foreach_table_root MEM_ROOT which can be used for allocating
2780 objects which lifetime is limited to dropping
2781 of single table.
2782
2783 @sa mysql_rm_table_no_locks().
2784
2785 @retval False - ok
2786 @retval True - error
2787 */
2788
2789 133711 static bool drop_base_table(THD *thd, const Drop_tables_ctx &drop_ctx,
2790 TABLE_LIST *table, bool atomic,
2791 std::set<handlerton *> *post_ddl_htons,
2792 Foreign_key_parents_invalidator *fk_invalidator,
2793 std::vector<MDL_ticket *> *safe_to_release_mdl,
2794 MEM_ROOT *foreach_table_root) {
2795 char path[FN_REFLEN + 1];
2796
2797 /* Check that we have an exclusive lock on the table to be dropped. */
2798
2/4
✓ Branch 0 taken 133711 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 133711 times.
133711 assert(thd->mdl_context.owns_equal_or_stronger_lock(
2799 MDL_key::TABLE, table->db, table->table_name, MDL_EXCLUSIVE));
2800
2801 /*
2802 Good point to check if we were killed for non-atomic tables group.
2803 All previous tables are dropped both in SE and data-dictionary and
2804 corresponding DROP TABLE statements are written to binary log.
2805 We didn't do anything for the current table yet.
2806
2807 For atomic tables the exact place of this check should not matter.
2808 */
2809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 133711 times.
133711 if (thd->killed) return true;
2810
2811 133711 const dd::Table *table_def = nullptr;
2812
4/8
✓ Branch 0 taken 133711 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 133711 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 133711 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 133711 times.
133711 if (thd->dd_client()->acquire(table->db, table->table_name, &table_def))
2813 return true;
2814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 133711 times.
133711 assert(table_def != nullptr);
2815
2816
4/8
✓ Branch 0 taken 133711 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 133711 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 133711 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 133711 times.
133711 if (table_def && table_def->hidden() == dd::Abstract_table::HT_HIDDEN_SE) {
2817 my_error(ER_NO_SUCH_TABLE, MYF(0), table->db, table->table_name);
2818 assert(true);
2819 return true;
2820 }
2821
2822 // Drop table from secondary engine.
2823
2/4
✓ Branch 0 taken 133711 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 133711 times.
133711 if (secondary_engine_unload_table(thd, table->db, table->table_name,
2824 *table_def, false))
2825 return true; /* purecov: inspected */
2826
2827 133711 handlerton *hton{nullptr};
2828
2/4
✓ Branch 0 taken 133711 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 133711 times.
133711 if (dd::table_storage_engine(thd, table_def, &hton)) {
2829 assert(false);
2830 return true;
2831 }
2832
2833 133711 histograms::results_map results;
2834 bool histogram_error =
2835
1/2
✓ Branch 0 taken 133711 times.
✗ Branch 1 not taken.
133711 histograms::drop_all_histograms(thd, *table, *table_def, results);
2836
2837
4/6
✓ Branch 0 taken 133711 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 133710 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
133711 DBUG_EXECUTE_IF("fail_after_drop_histograms", {
2838 my_error(ER_UNABLE_TO_DROP_COLUMN_STATISTICS, MYF(0), "dummy_column",
2839 table->db, table->table_name);
2840 histogram_error = true;
2841 });
2842
2843
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 133710 times.
133711 if (histogram_error) {
2844 /*
2845 Do a rollback request, so that we avoid commit from being called at a
2846 later stage.
2847 */
2848 1 thd->transaction_rollback_request = true;
2849 1 return true;
2850 }
2851
2852
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 133647 times.
133710 if (thd->locked_tables_mode) {
2853 /*
2854 Under LOCK TABLES we still have table open at this point.
2855 Close it and remove all instances from Table/Table Definition
2856 cache.
2857
2858 Note that we won't try to reopen tables in storage engines
2859 supporting atomic DDL those removal will be later rolled back
2860 thanks to some error. Such situations should be fairly rare.
2861 */
2862
1/2
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
63 close_all_tables_for_name(thd, table->db, table->table_name, true);
2863
2864 /*
2865 Find out if it is going to be safe to release MDL after dropping
2866 table under LOCK TABLES. It is not if we are dropping parent and
2867 leave child table around and locked.
2868 */
2869 63 bool safe_to_release = true;
2870
2871
2/4
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 63 times.
63 if (!table_def->foreign_key_parents().empty()) {
2872 // We don't have SEs which support FKs and not atomic DDL at the moment.
2873 assert(atomic);
2874
2875 for (const dd::Foreign_key_parent *fk :
2876 table_def->foreign_key_parents()) {
2877 if (my_strcasecmp(table_alias_charset, fk->child_schema_name().c_str(),
2878 table->db) == 0 &&
2879 my_strcasecmp(table_alias_charset, fk->child_table_name().c_str(),
2880 table->table_name) == 0)
2881 continue;
2882
2883 bool child_dropped = false;
2884
2885 for (TABLE_LIST *dropped : drop_ctx.base_atomic_tables) {
2886 if (my_strcasecmp(table_alias_charset,
2887 fk->child_schema_name().c_str(),
2888 dropped->db) == 0 &&
2889 my_strcasecmp(table_alias_charset, fk->child_table_name().c_str(),
2890 dropped->table_name) == 0) {
2891 child_dropped = true;
2892 break;
2893 }
2894 }
2895
2896 if (!child_dropped) {
2897 char buff_db[NAME_LEN + 1];
2898 char buff_table[NAME_LEN + 1];
2899
2900 my_stpncpy(buff_db, fk->child_schema_name().c_str(), NAME_LEN);
2901 my_stpncpy(buff_table, fk->child_table_name().c_str(), NAME_LEN);
2902
2903 /*
2904 In lower-case-table-names == 2 mode we store original versions of
2905 table and db names in the data-dictionary. Hence they need to be
2906 lowercased to produce correct MDL key.
2907 */
2908 if (lower_case_table_names == 2) {
2909 /* purecov: begin inspected */
2910 my_casedn_str(system_charset_info, buff_db);
2911 my_casedn_str(system_charset_info, buff_table);
2912 /* purecov: end */
2913 }
2914
2915 if (thd->mdl_context.owns_equal_or_stronger_lock(
2916 MDL_key::TABLE, buff_db, buff_table,
2917 MDL_SHARED_NO_READ_WRITE)) {
2918 /*
2919 Child is not going to be dropped and locked in mode which
2920 requires foreign key checks. It is not safe to release MDL.
2921 */
2922 safe_to_release = false;
2923 break;
2924 }
2925 }
2926 }
2927 }
2928
2929
1/2
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
63 if (safe_to_release)
2930
1/2
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
63 safe_to_release_mdl->push_back(table->mdl_request.ticket);
2931 } else {
2932
1/2
✓ Branch 0 taken 133647 times.
✗ Branch 1 not taken.
133647 tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db, table->table_name,
2933 false);
2934 }
2935
2936 /*
2937 If the table being dropped is a internal temporary table that was
2938 created by ALTER TABLE, we need to mark it as internal tmp table.
2939 This will enable us to build the filename as we build during ALTER
2940 TABLE.
2941 */
2942
3/4
✓ Branch 0 taken 133710 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 133708 times.
133710 if (table_def->hidden() == dd::Abstract_table::HT_HIDDEN_DDL)
2943 2 table->internal_tmp_table = true;
2944
2945
1/2
✓ Branch 0 taken 133710 times.
✗ Branch 1 not taken.
133710 (void)build_table_filename(path, sizeof(path) - 1, table->db,
2946 table->table_name, "",
2947
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 133708 times.
133710 table->internal_tmp_table ? FN_IS_TMP : 0);
2948
2949 /*
2950 Use memory root that is freed right after table processing for allocating
2951 dummy handler object for calling handler::delete_table() in order to avoid
2952 gobbling up memory when lots of tables are deleted.
2953 */
2954 133710 MEM_ROOT *save_thd_mem_root = thd->mem_root;
2955 133710 thd->mem_root = foreach_table_root;
2956
2957 267419 int error = ha_delete_table(thd, hton, path, table->db, table->table_name,
2958
1/2
✓ Branch 0 taken 133709 times.
✗ Branch 1 not taken.
133710 table_def, !drop_ctx.drop_database);
2959
2960 133709 thd->mem_root = save_thd_mem_root;
2961
2962 /*
2963 Table was present in data-dictionary but is missing in storage engine.
2964 This situation can occur for SEs which don't support atomic DDL due
2965 to crashes. In this case we allow table removal from data-dictionary
2966 and reporting success if IF EXISTS clause was specified.
2967
2968 Such situation should not be possible for SEs supporting atomic DDL,
2969 but we still play safe even in this case and allow table removal.
2970 */
2971
4/6
✓ Branch 0 taken 96428 times.
✓ Branch 1 taken 37281 times.
✓ Branch 2 taken 96428 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 96428 times.
✗ Branch 5 not taken.
133709 assert(!atomic || (error != ENOENT && error != HA_ERR_NO_SUCH_TABLE));
2972
2973
4/4
✓ Branch 0 taken 133697 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 133685 times.
133709 if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) &&
2974
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 5 times.
24 drop_ctx.if_exists) {
2975 19 error = 0;
2976
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 thd->clear_error();
2977 }
2978
2979
4/6
✓ Branch 0 taken 96428 times.
✓ Branch 1 taken 37281 times.
✓ Branch 2 taken 96428 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 96428 times.
✗ Branch 5 not taken.
133709 if (atomic && hton->post_ddl) post_ddl_htons->insert(hton);
2980
2981
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 133691 times.
133709 if (error) {
2982
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (error == HA_ERR_ROW_IS_REFERENCED)
2983 my_error(ER_ROW_IS_REFERENCED, MYF(0));
2984
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 else if (error == HA_ERR_TOO_MANY_CONCURRENT_TRXS)
2985 my_error(HA_ERR_TOO_MANY_CONCURRENT_TRXS, MYF(0));
2986 else {
2987 18 String tbl_name;
2988
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 append_table_name(&tbl_name, table);
2989
6/8
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 13 times.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
18 my_error(((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE)
2990 ? ER_ENGINE_CANT_DROP_MISSING_TABLE
2991 : ER_ENGINE_CANT_DROP_TABLE),
2992 MYF(0), tbl_name.c_ptr());
2993 18 }
2994 18 return true;
2995 }
2996
2997 #ifdef HAVE_PSI_SP_INTERFACE
2998
1/2
✓ Branch 0 taken 133691 times.
✗ Branch 1 not taken.
133691 remove_all_triggers_from_perfschema(table->db, *table_def);
2999 #endif
3000 /*
3001 Remove table from data-dictionary and immediately commit this change
3002 if we are removing table in SE which does not support atomic DDL.
3003 This way chances of SE and data-dictionary getting out of sync in
3004 case of crash are reduced.
3005
3006 Things will go bad if we will fail to delete table from data-dictionary
3007 as table is already gone in SE. But this should be really rare situation
3008 (OOM, out of disk space, bugs). Also user can fix it by running DROP TABLE
3009 IF EXISTS on the same table again.
3010
3011 Don't commit the changes if table belongs to SE supporting atomic DDL.
3012 */
3013
3014
1/2
✓ Branch 0 taken 133691 times.
✗ Branch 1 not taken.
133691 if (adjust_fk_children_for_parent_drop(thd, table->db, table->table_name,
3015
2/4
✓ Branch 0 taken 133691 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 133691 times.
267382 table_def, hton) ||
3016
2/4
✓ Branch 0 taken 133691 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 133691 times.
133691 adjust_fk_parents(thd, table->db, table->table_name, false, nullptr))
3017 return true;
3018
3019
6/10
✓ Branch 0 taken 133691 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 133691 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 133691 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1026 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1026 times.
✓ Branch 9 taken 133691 times.
134717 for (const dd::Foreign_key *fk : table_def->foreign_keys()) {
3020
2/4
✓ Branch 0 taken 1026 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1026 times.
✗ Branch 3 not taken.
1026 if (my_strcasecmp(table_alias_charset,
3021 fk->referenced_table_schema_name().c_str(),
3022
4/4
✓ Branch 0 taken 1011 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 997 times.
2037 table->db) == 0 &&
3023
4/6
✓ Branch 0 taken 1011 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1011 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 29 times.
✓ Branch 5 taken 982 times.
1011 my_strcasecmp(table_alias_charset, fk->referenced_table_name().c_str(),
3024 table->table_name) == 0)
3025 29 continue;
3026
3027 char buff_db[NAME_LEN + 1];
3028 char buff_table[NAME_LEN + 1];
3029
1/2
✓ Branch 0 taken 997 times.
✗ Branch 1 not taken.
997 my_stpncpy(buff_db, fk->referenced_table_schema_name().c_str(), NAME_LEN);
3030
1/2
✓ Branch 0 taken 997 times.
✗ Branch 1 not taken.
997 my_stpncpy(buff_table, fk->referenced_table_name().c_str(), NAME_LEN);
3031
3032 /*
3033 In lower-case-table-names == 2 mode we store original versions of table
3034 and db names in the data-dictionary. Hence they need to be lowercased
3035 before being used for TDC invalidation.
3036 */
3037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 997 times.
997 if (lower_case_table_names == 2) {
3038 my_casedn_str(system_charset_info, buff_db);
3039 my_casedn_str(system_charset_info, buff_table);
3040 }
3041
3042 // We don't have any SEs which support FKs but do not support atomic DDL.
3043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 997 times.
997 assert(atomic);
3044
3045
1/2
✓ Branch 0 taken 997 times.
✗ Branch 1 not taken.
997 fk_invalidator->add(buff_db, buff_table, hton);
3046 }
3047
3048 133691 dd::Schema_MDL_locker mdl_locker(thd);
3049
2/4
✓ Branch 0 taken 133691 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 133691 times.
133691 if (mdl_locker.ensure_locked(table->db)) return true;
3050
1/2
✓ Branch 0 taken 133691 times.
✗ Branch 1 not taken.
133691 bool result = dd::drop_table(thd, table->db, table->table_name, *table_def);
3051
3052
3/4
✓ Branch 0 taken 37276 times.
✓ Branch 1 taken 96415 times.
✓ Branch 2 taken 37276 times.
✗ Branch 3 not taken.
133691 if (!atomic) result = trans_intermediate_ddl_commit(thd, result);
3053
3054 /*
3055 In DROP DATABASE we can safely skip updating dependent views belonging
3056 to the same database if we know that they will be dropped atomically
3057 with our table.
3058 */
3059
1/2
✓ Branch 0 taken 133691 times.
✗ Branch 1 not taken.
133691 result |= mark_referencing_views_invalid(thd, table,
3060
2/2
✓ Branch 0 taken 9052 times.
✓ Branch 1 taken 1179 times.
133691 (drop_ctx.drop_database && atomic),
3061
2/2
✓ Branch 0 taken 10231 times.
✓ Branch 1 taken 123460 times.
133691 !atomic, foreach_table_root);
3062
3063 133691 return result;
3064 133710 }
3065
3066 /**
3067 Execute the drop of a normal or temporary table.
3068
3069 @param thd Thread handler
3070 @param tables Tables to drop
3071 @param if_exists If set, don't give an error if table doesn't exists.
3072 In this case we give an warning of level 'NOTE'
3073 @param drop_temporary Only drop temporary tables
3074 @param drop_database This is DROP DATABASE statement. Drop views
3075 and handle binary logging in a special way.
3076 @param[out] dropped_non_atomic_flag Indicates whether we have dropped some
3077 tables in SEs which don't support atomic
3078 DDL.
3079 @param[out] post_ddl_htons Set of handlertons for tables in SEs supporting
3080 atomic DDL for which post-DDL hook needs to
3081 be called after statement commit or rollback.
3082 @param[out] fk_invalidator Set of parent tables which participate in FKs
3083 together with tables dropped and which entries
3084 in DD cache need to be invalidated as result
3085 of DROP operation.
3086 @param[out] safe_to_release_mdl Under LOCK TABLES set of metadata locks on
3087 tables dropped which is safe to release
3088 after DROP operation.
3089
3090 @retval False - ok
3091 @retval True - error
3092
3093 @note This function assumes that metadata locks have already been taken.
3094 It is also assumed that the tables have been removed from TDC.
3095
3096 @note This function assumes that temporary tables to be dropped have
3097 been pre-opened using corresponding table list elements.
3098
3099 @todo When logging to the binary log, we should log
3100 tmp_tables and transactional tables as separate statements if we
3101 are in a transaction; This is needed to get these tables into the
3102 cached binary log that is only written on COMMIT.
3103 The current code only writes DROP statements that only uses temporary
3104 tables to the cache binary log. This should be ok on most cases, but
3105 not all.
3106 */
3107
3108 156486 bool mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
3109 bool drop_temporary, bool drop_database,
3110 bool *dropped_non_atomic_flag,
3111 std::set<handlerton *> *post_ddl_htons,
3112 Foreign_key_parents_invalidator *fk_invalidator,
3113 std::vector<MDL_ticket *> *safe_to_release_mdl) {
3114
1/2
✓ Branch 0 taken 156486 times.
✗ Branch 1 not taken.
156486 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
3115
1/2
✓ Branch 0 taken 156486 times.
✗ Branch 1 not taken.
156486 Drop_tables_ctx drop_ctx(if_exists, drop_temporary, drop_database);
3116 156486 std::vector<MDL_ticket *> safe_to_release_mdl_atomic;
3117
3118 156486 bool default_db_doesnt_exist = false;
3119
3120
1/2
✓ Branch 0 taken 156486 times.
✗ Branch 1 not taken.
156486 DBUG_TRACE;
3121
3122 156486 *dropped_non_atomic_flag = false;
3123
3124
3/4
✓ Branch 0 taken 156486 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 156480 times.
156486 if (rm_table_sort_into_groups(thd, &drop_ctx, tables)) return true;
3125
3126 /*
3127 Figure out in which situation we are regarding GTID and different
3128 table groups.
3129 */
3130
3/4
✓ Branch 0 taken 156480 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 156474 times.
156480 if (rm_table_eval_gtid_and_table_groups_state(thd, &drop_ctx)) return true;
3131
3132
7/8
✓ Branch 0 taken 131267 times.
✓ Branch 1 taken 25207 times.
✓ Branch 2 taken 131267 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1038 times.
✓ Branch 5 taken 130229 times.
✓ Branch 6 taken 1038 times.
✓ Branch 7 taken 155436 times.
156474 if (!drop_ctx.if_exists && drop_ctx.has_any_nonexistent_tables()) {
3133 /*
3134 No IF EXISTS clause and some non-existing tables.
3135
3136 Fail before dropping any tables. This gives us nice "atomic" (succeed
3137 or don't drop anything) behavior for most common failure scenario even
3138 for tables which don't support atomic DDL.
3139
3140 Do this check after getting full list of missing tables to produce
3141 better error message.
3142 */
3143 1038 String wrong_tables;
3144
3145
4/6
✓ Branch 0 taken 1038 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1038 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1097 times.
✓ Branch 5 taken 1038 times.
2135 for (TABLE_LIST *table : drop_ctx.nonexistent_tables) {
3146
3/4
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 1038 times.
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
1097 if (wrong_tables.length()) wrong_tables.append(',');
3147
1/2
✓ Branch 0 taken 1097 times.
✗ Branch 1 not taken.
1097 append_table_name(&wrong_tables, table);
3148 }
3149
3150
2/4
✓ Branch 0 taken 1038 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1038 times.
✗ Branch 3 not taken.
1038 my_error(ER_BAD_TABLE_ERROR, MYF(0), wrong_tables.c_ptr());
3151 1038 return true;
3152 1038 }
3153
3154 /* Check if we are about to violate any foreign keys. */
3155
3/4
✓ Branch 0 taken 155436 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 155420 times.
155436 if (rm_table_check_fks(thd, &drop_ctx)) return true;
3156
3157
7/8
✓ Branch 0 taken 25197 times.
✓ Branch 1 taken 130223 times.
✓ Branch 2 taken 25197 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8927 times.
✓ Branch 5 taken 16270 times.
✓ Branch 6 taken 8927 times.
✓ Branch 7 taken 146493 times.
155420 if (drop_ctx.if_exists && drop_ctx.has_any_nonexistent_tables()) {
3158
4/6
✓ Branch 0 taken 8927 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8927 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11015 times.
✓ Branch 5 taken 8927 times.
19942 for (TABLE_LIST *table : drop_ctx.nonexistent_tables) {
3159 11015 String tbl_name;
3160
1/2
✓ Branch 0 taken 11015 times.
✗ Branch 1 not taken.
11015 append_table_name(&tbl_name, table);
3161
3/6
✓ Branch 0 taken 11015 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11015 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11015 times.
✗ Branch 5 not taken.
11015 push_warning_printf(thd, Sql_condition::SL_NOTE, ER_BAD_TABLE_ERROR,
3162 ER_THD(thd, ER_BAD_TABLE_ERROR), tbl_name.c_ptr());
3163 11015 }
3164 }
3165
3166 /* Non-existent temporary tables with IF EXISTS do not need any
3167 further processing */
3168
7/8
✓ Branch 0 taken 25197 times.
✓ Branch 1 taken 130223 times.
✓ Branch 2 taken 25197 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 750 times.
✓ Branch 5 taken 24447 times.
✓ Branch 6 taken 750 times.
✓ Branch 7 taken 154670 times.
155420 if (drop_ctx.if_exists && drop_ctx.has_tmp_nonexistent_tables()) {
3169
1/2
✓ Branch 0 taken 750 times.
✗ Branch 1 not taken.
750 drop_ctx.nonexistent_tables.clear();
3170
3171 /* If such tables were all we had, there is nothing else to do */
3172
1/2
✓ Branch 0 taken 750 times.
✗ Branch 1 not taken.
750 if (!drop_ctx.has_base_atomic_tables() &&
3173
2/4
✓ Branch 0 taken 750 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 750 times.
✗ Branch 3 not taken.
750 !drop_ctx.has_base_non_atomic_tables() &&
3174
3/4
✓ Branch 0 taken 750 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 724 times.
✓ Branch 3 taken 26 times.
750 !drop_ctx.has_tmp_trans_tables() &&
3175
8/12
✓ Branch 0 taken 750 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 724 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 701 times.
✓ Branch 5 taken 23 times.
✓ Branch 6 taken 701 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 701 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 701 times.
✓ Branch 11 taken 49 times.
1500 !drop_ctx.has_tmp_non_trans_tables() && !drop_ctx.has_views()) {
3176 701 return false;
3177 }
3178 }
3179
3180 /*
3181 Check early if default database exists. We don't want code responsible
3182 for dropping temporary tables fail due to this check after some tables
3183 were dropped already.
3184 */
3185
2/2
✓ Branch 0 taken 154121 times.
✓ Branch 1 taken 598 times.
154719 if (thd->db().str != nullptr) {
3186 154121 bool exists = false;
3187
2/4
✓ Branch 0 taken 154121 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 154121 times.
154121 if (dd::schema_exists(thd, thd->db().str, &exists)) return true;
3188 154121 default_db_doesnt_exist = !exists;
3189 }
3190
3191 MEM_ROOT foreach_table_root(key_memory_rm_table_foreach_root,
3192 154719 MEM_ROOT_BLOCK_SIZE);
3193
3194
3/4
✓ Branch 0 taken 154719 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33863 times.
✓ Branch 3 taken 120856 times.
154719 if (drop_ctx.has_base_non_atomic_tables()) {
3195 /*
3196 Handle base tables in storage engines which don't support atomic DDL.
3197
3198 Their drop can't be rolled back in case of crash or error. So we drop
3199 each such table individually and write to binlog a single-table DROP
3200 TABLE statement corresponding to this action right after it.
3201 This increases chances of SE, data-dictionary and binary log being in
3202 sync if crash occurs.
3203 This also handles case of error/statement being killed in a natural
3204 way - by the time when error occurs we already have logged all drops
3205 which were successful. So we don't need to write the whole failed
3206 statement with error code to binary log.
3207
3208 Note that we process non-atomic tables before atomic ones in order to
3209 avoid situations when DROP TABLES for mixed set of tables will fail
3210 and leave changes to atomic, "transactional" tables around.
3211 */
3212
4/6
✓ Branch 0 taken 33863 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33863 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37281 times.
✓ Branch 5 taken 33857 times.
71138 for (TABLE_LIST *table : drop_ctx.base_non_atomic_tables) {
3213
3/4
✓ Branch 0 taken 37281 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 37275 times.
37281 if (drop_base_table(thd, drop_ctx, table, false /* non-atomic */, nullptr,
3214 nullptr, safe_to_release_mdl, &foreach_table_root))
3215 6 goto err_with_rollback;
3216
3217 37275 *dropped_non_atomic_flag = true;
3218
3219
1/2
✓ Branch 0 taken 37275 times.
✗ Branch 1 not taken.
37275 drop_ctx.dropped_non_atomic.push_back(table);
3220
3221
2/2
✓ Branch 0 taken 37251 times.
✓ Branch 1 taken 24 times.
37275 if (!drop_ctx.has_gtid_many_table_groups()) {
3222 /*
3223 We don't have GTID assigned, or we have GTID assigned and this is
3224 single-table DROP TABLE for this specific table.
3225
3226 Write single-table DROP TABLE statement to binary log.
3227
3228 Do this even if table was dropped as part of DROP DATABASE statement,
3229 as this descreases chance of things getting out of sync in case of
3230 crash.
3231 */
3232
2/2
✓ Branch 0 taken 1171 times.
✓ Branch 1 taken 36080 times.
37251 if (drop_ctx.drop_database) {
3233
2/2
✓ Branch 0 taken 1163 times.
✓ Branch 1 taken 8 times.
1171 if (mysql_bin_log.is_open()) {
3234 1163 String built_query;
3235
3236 1163 built_query.set_charset(system_charset_info);
3237
1/2
✓ Branch 0 taken 1163 times.
✗ Branch 1 not taken.
1163 built_query.append("DROP TABLE IF EXISTS ");
3238
3239
1/2
✓ Branch 0 taken 1163 times.
✗ Branch 1 not taken.
1163 append_identifier(thd, &built_query, table->table_name,
3240 table->table_name_length, system_charset_info,
3241 thd->charset());
3242
3243
1/2
✓ Branch 0 taken 1163 times.
✗ Branch 1 not taken.
1163 built_query.append(" /* generated by server */");
3244
3245
1/2
✓ Branch 0 taken 1163 times.
✗ Branch 1 not taken.
1163 thd->add_to_binlog_accessed_dbs(table->db);
3246
3247 1163 Query_log_event qinfo(thd, built_query.ptr(), built_query.length(),
3248
1/2
✓ Branch 0 taken 1163 times.
✗ Branch 1 not taken.
2326 false, true, false, 0);
3249 1163 qinfo.db = table->db;
3250 1163 qinfo.db_len = table->db_length;
3251
3252
2/4
✓ Branch 0 taken 1163 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1163 times.
1163 if (mysql_bin_log.write_event(&qinfo)) goto err_with_rollback;
3253
2/4
✓ Branch 0 taken 1163 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1163 times.
✗ Branch 3 not taken.
1163 }
3254 } else {
3255 Drop_tables_query_builder built_query(
3256 36080 thd, false /* no TEMPORARY */, drop_ctx.if_exists,
3257
1/2
✓ Branch 0 taken 36080 times.
✗ Branch 1 not taken.
36080 false /* stmt binlog cache */, false /* db exists */);
3258
3259
1/2
✓ Branch 0 taken 36080 times.
✗ Branch 1 not taken.
36080 built_query.add_table(table);
3260
3261 108240 if (thd->variables.binlog_ddl_skip_rewrite ||
3262
1/2
✓ Branch 0 taken 36080 times.
✗ Branch 1 not taken.
36080 thd->system_thread == SYSTEM_THREAD_SLAVE_SQL ||
3263
7/8
✓ Branch 0 taken 36080 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30761 times.
✓ Branch 3 taken 5319 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 30760 times.
✓ Branch 6 taken 5320 times.
✓ Branch 7 taken 30760 times.
102921 thd->system_thread == SYSTEM_THREAD_SLAVE_WORKER ||
3264 30761 thd->is_binlog_applier()) {
3265
4/8
✓ Branch 0 taken 5320 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5320 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5320 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 5320 times.
5320 if (write_bin_log(thd, true, thd->query().str, thd->query().length,
3266 false)) {
3267 goto err_with_rollback;
3268 }
3269
3270 } else {
3271
2/4
✓ Branch 0 taken 30760 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 30760 times.
30760 if (built_query.write_bin_log()) goto err_with_rollback;
3272 }
3273
1/2
✓ Branch 0 taken 36080 times.
✗ Branch 1 not taken.
36080 }
3274
3275
6/6
✓ Branch 0 taken 5777 times.
✓ Branch 1 taken 31474 times.
✓ Branch 2 taken 140 times.
✓ Branch 3 taken 5637 times.
✓ Branch 4 taken 31614 times.
✓ Branch 5 taken 5637 times.
43028 if (drop_ctx.has_no_gtid_single_table_group() ||
3276 5777 drop_ctx.has_gtid_single_table_group()) {
3277 /*
3278 This was a single-table DROP TABLE for this specific table.
3279 Commit change to binary log and/or mark GTID as executed instead.
3280 In theory, we also can update slave info atomically with binlog/
3281 GTID changes,
3282 */
3283
5/10
✓ Branch 0 taken 31614 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31614 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 31614 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 31614 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 31614 times.
31614 if (trans_commit_stmt(thd) || trans_commit_implicit(thd))
3284 goto err_with_rollback;
3285 } else {
3286 /*
3287 We don't have GTID assigned and this is not single-table
3288 DROP TABLE. Commit change to binary log (if there was any)
3289 and get GTID assigned for our single-table change. Do not
3290 release ANONYMOUS_GTID ownership yet as there can be more
3291 tables to drop and corresponding statements to write to
3292 binary log. Do not update slave info as there might be more
3293 groups.
3294 */
3295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5637 times.
5637 assert(drop_ctx.has_no_gtid_many_table_groups());
3296
3297 5637 thd->is_commit_in_middle_of_statement = true;
3298
4/8
✓ Branch 0 taken 5637 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5637 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5637 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 5637 times.
5637 bool error = (trans_commit_stmt(thd) || trans_commit_implicit(thd));
3299 5637 thd->is_commit_in_middle_of_statement = false;
3300
3301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5637 times.
5637 if (error) goto err_with_rollback;
3302 }
3303 } else {
3304 /*
3305 We have GTID assigned and several tables from SEs which don't support
3306 atomic DDL, or tables in different groups. Postpone writing to binary
3307 log/marking GTID as executed until all tables are processed.
3308
3309 Nothing to commit here as change to data-dictionary is already
3310 committed earlier.
3311 */
3312 }
3313
1/2
✓ Branch 0 taken 37275 times.
✗ Branch 1 not taken.
37275 foreach_table_root.ClearForReuse();
3314 }
3315 }
3316
3317
8/10
✓ Branch 0 taken 154713 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 89490 times.
✓ Branch 3 taken 65223 times.
✓ Branch 4 taken 89490 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 89446 times.
✓ Branch 7 taken 44 times.
✓ Branch 8 taken 73294 times.
✓ Branch 9 taken 81419 times.
244159 if (drop_ctx.has_base_atomic_tables() || drop_ctx.has_views() ||
3318
3/4
✓ Branch 0 taken 89446 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8027 times.
✓ Branch 3 taken 81419 times.
89446 drop_ctx.has_base_nonexistent_tables()) {
3319 /*
3320 Handle base tables in SEs which support atomic DDL, as well as views
3321 and non-existent tables.
3322
3323 Drop all these objects in SE and data-dictionary in a single atomic
3324 transaction. Write corresponding multi-table DROP TABLE statement to
3325 the binary log as part of the same transaction.
3326 */
3327
3/4
✓ Branch 0 taken 73183 times.
✓ Branch 1 taken 111 times.
✓ Branch 2 taken 73183 times.
✗ Branch 3 not taken.
73294 DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table");
3328
4/6
✓ Branch 0 taken 73294 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 73293 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
73294 DBUG_EXECUTE_IF("sleep_before_no_locks_delete_table", my_sleep(100000););
3329
3330
4/6
✓ Branch 0 taken 73294 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 73291 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
73294 DBUG_EXECUTE_IF("rm_table_no_locks_abort_before_atomic_tables", {
3331 my_error(ER_UNKNOWN_ERROR, MYF(0));
3332 goto err_with_rollback;
3333 });
3334
3335
4/6
✓ Branch 0 taken 73291 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73291 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 96430 times.
✓ Branch 5 taken 73273 times.
169703 for (TABLE_LIST *table : drop_ctx.base_atomic_tables) {
3336
3/4
✓ Branch 0 taken 96429 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 96412 times.
96430 if (drop_base_table(thd, drop_ctx, table, true /* atomic */,
3337 post_ddl_htons, fk_invalidator,
3338 &safe_to_release_mdl_atomic, &foreach_table_root)) {
3339 17 goto err_with_rollback;
3340 }
3341
1/2
✓ Branch 0 taken 96412 times.
✗ Branch 1 not taken.
96412 foreach_table_root.ClearForReuse();
3342 }
3343
3344
4/6
✓ Branch 0 taken 73273 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 73236 times.
✓ Branch 4 taken 37 times.
✗ Branch 5 not taken.
73273 DBUG_EXECUTE_IF("rm_table_no_locks_abort_after_atomic_tables", {
3345 my_error(ER_UNKNOWN_ERROR, MYF(0));
3346 goto err_with_rollback;
3347 });
3348
3349
4/6
✓ Branch 0 taken 73236 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73236 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 858 times.
✓ Branch 5 taken 73236 times.
74094 for (TABLE_LIST *table : drop_ctx.views) {
3350 /* Check that we have an exclusive lock on the view to be dropped. */
3351
2/4
✓ Branch 0 taken 858 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 858 times.
858 assert(thd->mdl_context.owns_equal_or_stronger_lock(
3352 MDL_key::TABLE, table->db, table->table_name, MDL_EXCLUSIVE));
3353
3354
1/2
✓ Branch 0 taken 858 times.
✗ Branch 1 not taken.
858 tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db, table->table_name,
3355 false);
3356
3357 858 const dd::View *view = nullptr;
3358
4/8
✓ Branch 0 taken 858 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 858 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 858 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 858 times.
858 if (thd->dd_client()->acquire(table->db, table->table_name, &view))
3359 goto err_with_rollback;
3360
3361 /*
3362 Since we drop views here only if called by DROP DATABASE:
3363 - We can safely skip marking depending views as invalid if they
3364 belong to the same database.
3365 - No need to log anything.
3366 */
3367
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 858 times.
858 assert(drop_ctx.drop_database);
3368
3369
3/6
✓ Branch 0 taken 858 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 858 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 858 times.
1716 if (thd->dd_client()->drop(view) ||
3370
2/4
✓ Branch 0 taken 858 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 858 times.
858 mark_referencing_views_invalid(thd, table, true, false,
3371 &foreach_table_root))
3372 goto err_with_rollback;
3373
3374
1/2
✓ Branch 0 taken 858 times.
✗ Branch 1 not taken.
858 foreach_table_root.ClearForReuse();
3375 }
3376
3377 #ifndef NDEBUG
3378
4/6
✓ Branch 0 taken 73236 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73236 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10260 times.
✓ Branch 5 taken 73236 times.
83496 for (TABLE_LIST *table : drop_ctx.nonexistent_tables) {
3379 /*
3380 Check that we have an exclusive lock on the table which we were
3381 supposed drop.
3382 */
3383
2/4
✓ Branch 0 taken 10260 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10260 times.
10260 assert(thd->mdl_context.owns_equal_or_stronger_lock(
3384 MDL_key::TABLE, table->db, table->table_name, MDL_EXCLUSIVE));
3385 }
3386 #endif
3387
3388
3/4
✓ Branch 0 taken 73127 times.
✓ Branch 1 taken 109 times.
✓ Branch 2 taken 73127 times.
✗ Branch 3 not taken.
73236 DEBUG_SYNC(thd, "rm_table_no_locks_before_binlog");
3389
3390 73236 int error = 0;
3391
3392
2/2
✓ Branch 0 taken 70309 times.
✓ Branch 1 taken 2927 times.
73236 if (drop_ctx.drop_database) {
3393 /*
3394 This is DROP DATABASE.
3395
3396 If we don't have GTID assigned removal of tables from this group will be
3397 logged as DROP DATABASE and committed atomically, together with removal
3398 of events and stored routines, by the caller.
3399
3400 The same thing should happen if we have GTID assigned and tables only
3401 from this group.
3402
3403 If we have GTID assigned and mix of tables from SEs which support atomic
3404 DDL and which don't support it we will still behave in similar way.
3405 If the whole statement succeeds removal of tables from all groups will
3406 be logged as single DROP DATABASE statement. In case of failure we will
3407 report special error, but in addition it makes sense to rollback all
3408 changes to tables in SEs supporting atomic DDL.
3409
3410 So do nothing here in all three cases described above.
3411 */
3412
2/2
✓ Branch 0 taken 70301 times.
✓ Branch 1 taken 8 times.
70309 } else if (!drop_ctx.has_gtid_many_table_groups()) {
3413 /*
3414 We don't have GTID assigned, or we have GTID assigned and our DROP
3415 TABLES only drops table from this group, so we have fully atomic
3416 multi-table DROP TABLES statement.
3417
3418 If we have not dropped any tables at all (we have only non-existing
3419 tables) we don't have transaction started. We can't use binlog's
3420 trx cache in this case as it requires active transaction with valid
3421 XID.
3422 */
3423 Drop_tables_query_builder built_query(
3424 70301 thd, false /* no TEMPORARY */, drop_ctx.if_exists,
3425 /* stmt or trx cache. */
3426
2/4
✓ Branch 0 taken 70301 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 70301 times.
✗ Branch 3 not taken.
70301 drop_ctx.has_base_atomic_tables(), false /* db exists */);
3427
3428
1/2
✓ Branch 0 taken 70301 times.
✗ Branch 1 not taken.
70301 built_query.add_array(drop_ctx.base_atomic_tables);
3429
1/2
✓ Branch 0 taken 70301 times.
✗ Branch 1 not taken.
70301 built_query.add_array(drop_ctx.nonexistent_tables);
3430
3431 70301 thd->thread_specific_used = true;
3432
3433 210888 if (thd->variables.binlog_ddl_skip_rewrite ||
3434
2/2
✓ Branch 0 taken 70274 times.
✓ Branch 1 taken 12 times.
70286 thd->system_thread == SYSTEM_THREAD_SLAVE_SQL ||
3435
8/8
✓ Branch 0 taken 70286 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 61812 times.
✓ Branch 3 taken 8462 times.
✓ Branch 4 taken 39 times.
✓ Branch 5 taken 61773 times.
✓ Branch 6 taken 8528 times.
✓ Branch 7 taken 61773 times.
202399 thd->system_thread == SYSTEM_THREAD_SLAVE_WORKER ||
3436 61812 thd->is_binlog_applier()) {
3437
3/6
✓ Branch 0 taken 8528 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8528 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8528 times.
8528 if (write_bin_log(thd, true, thd->query().str, thd->query().length,
3438
2/4
✓ Branch 0 taken 8528 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8528 times.
✗ Branch 3 not taken.
8528 drop_ctx.has_base_atomic_tables())) {
3439 goto err_with_rollback;
3440 }
3441
3442 } else {
3443
3/4
✓ Branch 0 taken 61773 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 61771 times.
61773 if (built_query.write_bin_log()) goto err_with_rollback;
3444 }
3445
3446
6/6
✓ Branch 0 taken 2703 times.
✓ Branch 1 taken 67596 times.
✓ Branch 2 taken 1425 times.
✓ Branch 3 taken 1278 times.
✓ Branch 4 taken 69021 times.
✓ Branch 5 taken 1278 times.
73002 if (drop_ctx.has_no_gtid_single_table_group() ||
3447 2703 drop_ctx.has_gtid_single_table_group()) {
3448 /*
3449 This is fully atomic multi-table DROP TABLES.
3450 Commit changes to SEs, data-dictionary and binary log/or
3451 and mark GTID as executed/update slave info tables atomically.
3452 */
3453
5/8
✓ Branch 0 taken 69021 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69021 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 69000 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 68999 times.
69021 error = (trans_commit_stmt(thd) || trans_commit_implicit(thd));
3454 } else {
3455 /*
3456 We don't have GTID assigned and this is not fully-atomic DROP TABLES.
3457 Commit changes to SE, data-dictionary and binary log and get GTID
3458 assigned for our changes.
3459 Do not release ANONYMOUS_GTID ownership and update slave info yet
3460 as there can be more tables (e.g. temporary) to drop and corresponding
3461 statements to write to binary log.
3462 */
3463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1278 times.
1278 assert(drop_ctx.has_no_gtid_many_table_groups());
3464
3465 1278 thd->is_commit_in_middle_of_statement = true;
3466
4/8
✓ Branch 0 taken 1278 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1278 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1278 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1278 times.
1278 error = (trans_commit_stmt(thd) || trans_commit_implicit(thd));
3467 1278 thd->is_commit_in_middle_of_statement = false;
3468 }
3469
3470
4/4
✓ Branch 0 taken 70277 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 70255 times.
70278 if (!error && thd->locked_tables_mode)
3471
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 safe_to_release_mdl->insert(safe_to_release_mdl->end(),
3472 safe_to_release_mdl_atomic.begin(),
3473 safe_to_release_mdl_atomic.end());
3474
2/2
✓ Branch 0 taken 70278 times.
✓ Branch 1 taken 2 times.
70280 } else {
3475 /*
3476 We have GTID assigned, some tables from SEs which don't support
3477 atomic DDL and some from SEs which do.
3478
3479 Postpone writing to binary log and marking GTID as executed until
3480 later stage. We also postpone committing removal of tables in SEs
3481 supporting atomic DDL and corresponding changes to the data-
3482 dictionary until the same stage. This allows to minimize change
3483 difference between SEs/data-dictionary and binary log in case of
3484 crash.
3485
3486 If crash occurs binary log won't contain any traces about removal
3487 of tables in both SEs support and not-supporting atomic DDL.
3488 And only tables in SEs not supporting atomic DDL will be missing
3489 from SEs and the data-dictionary. Since removal of tables in SEs
3490 supporting atomic DDL will be rolled back during recovery.
3491 */
3492 }
3493
3494
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 73212 times.
73213 if (error) goto err_with_rollback;
3495 }
3496
3497
6/6
✓ Branch 0 taken 151442 times.
✓ Branch 1 taken 3189 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 151433 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 154622 times.
154631 if (!drop_ctx.drop_database && drop_ctx.has_gtid_many_table_groups()) {
3498 /*
3499 We DROP TABLES statement with GTID assigned and either several tables
3500 from SEs which don't support atomic DDL, or at least one table from
3501 such SE and some tables from SEs which do support atomic DDL.
3502
3503 We have postponed write to binlog earlier. Now it is time to do it.
3504
3505 If we don't have active transaction at this point (i.e. no tables
3506 in SE supporting atomic DDL were dropped) we can't use binlog's trx
3507 cache for this. as it requires active transaction with valid XID.
3508 If we have active transaction (i.e. some tables in SE supporting
3509 atomic DDL were dropped) we have to use trx cache to ensure that
3510 our transaction is properly recovered in case of crash/restart.
3511 */
3512 Drop_tables_query_builder built_query(
3513 9 thd, false /* no TEMPORARY */, drop_ctx.if_exists,
3514 /* trx or stmt cache */
3515
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 drop_ctx.has_base_atomic_tables(), false /* db exists */);
3516
3517
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 built_query.add_array(drop_ctx.base_non_atomic_tables);
3518
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 built_query.add_array(drop_ctx.base_atomic_tables);
3519
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 built_query.add_array(drop_ctx.nonexistent_tables);
3520
3521
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 if (built_query.write_bin_log()) goto err_with_rollback;
3522
3523 /*
3524 Commit our changes to the binary log (if any) and mark GTID
3525 as executed. This also commits removal of tables in SEs
3526 supporting atomic DDL from SE and the data-dictionary.
3527 In theory, we can update slave info atomically with binlog/GTID
3528 changes here.
3529 */
3530
5/10
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 9 times.
9 if (trans_commit_stmt(thd) || trans_commit_implicit(thd))
3531 goto err_with_rollback;
3532
3533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (thd->locked_tables_mode)
3534 safe_to_release_mdl->insert(safe_to_release_mdl->end(),
3535 safe_to_release_mdl_atomic.begin(),
3536 safe_to_release_mdl_atomic.end());
3537
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 }
3538
3539
2/2
✓ Branch 0 taken 151442 times.
✓ Branch 1 taken 3189 times.
154631 if (!drop_ctx.drop_database) {
3540 /*
3541 Unless this is DROP DATABASE removal of tables in SEs
3542 supporting foreign keys is already committed at this point.
3543 So we can invalidate cache entries for parent tables.
3544 */
3545
1/2
✓ Branch 0 taken 151442 times.
✗ Branch 1 not taken.
151442 fk_invalidator->invalidate(thd);
3546 }
3547
3548 /*
3549 Dropping of temporary tables cannot be rolled back. On the other hand it
3550 can't fail at this stage. So to get nice error handling behavior
3551 (either fully succeed or fail and do nothing (if there are no tables
3552 which don't support atomic DDL)) we process such tables after we are
3553 done with base tables.
3554
3555 DROP TEMPORARY TABLES does not commit an ongoing transaction. So in
3556 some circumstances we must binlog changes to non-transactional
3557 ahead of transaction (so we need to tell binlog that these changes
3558 are non-transactional), while changes to transactional tables
3559 should be binlogged as part of transaction.
3560 */
3561
3/4
✓ Branch 0 taken 154631 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5622 times.
✓ Branch 3 taken 149009 times.
154631 if (drop_ctx.has_tmp_non_trans_tables()) {
3562
4/6
✓ Branch 0 taken 5622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5622 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5988 times.
✓ Branch 5 taken 5622 times.
11610 for (auto *table : drop_ctx.tmp_non_trans_tables) {
3563 /*
3564 Don't check THD::killed flag. We can't rollback deletion of
3565 temporary table, so aborting on KILL will make DROP TABLES
3566 less atomic.
3567 OTOH it is unlikely that we have many temporary tables to drop
3568 so being immune to KILL is not that horrible in most cases.
3569 */
3570
1/2
✓ Branch 0 taken 5988 times.
✗ Branch 1 not taken.
5988 drop_temporary_table(thd, table);
3571 }
3572
1/2
✓ Branch 0 taken 5622 times.
✗ Branch 1 not taken.
5622 thd->get_transaction()->mark_dropped_temp_table(Transaction_ctx::STMT);
3573 }
3574
3575
3/4
✓ Branch 0 taken 154631 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 684 times.
✓ Branch 3 taken 153947 times.
154631 if (drop_ctx.has_tmp_non_trans_tables_to_binlog()) {
3576
2/4
✓ Branch 0 taken 684 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 684 times.
684 assert(drop_ctx.has_tmp_non_trans_tables());
3577 /*
3578 Handle non-transactional temporary tables.
3579 */
3580
3581 /* DROP DATABASE doesn't deal with temporary tables. */
3582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 684 times.
684 assert(!drop_ctx.drop_database);
3583
3584 /*
3585 If default database does not exist, set
3586 'is_drop_tmp_if_exists_with_no_defaultdb flag to 'true',
3587 so that the 'DROP TEMPORARY TABLE IF EXISTS' command is logged
3588 with a fully-qualified table name and we don't write "USE db"
3589 prefix.
3590 */
3591 684 const bool is_drop_tmp_if_exists_with_no_defaultdb =
3592
3/4
✓ Branch 0 taken 398 times.
✓ Branch 1 taken 286 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 398 times.
684 (drop_ctx.if_exists && default_db_doesnt_exist);
3593 Drop_tables_query_builder built_query(
3594 684 thd, true /* DROP TEMPORARY */, drop_ctx.if_exists,
3595
1/2
✓ Branch 0 taken 684 times.
✗ Branch 1 not taken.
684 false /* stmt cache */, is_drop_tmp_if_exists_with_no_defaultdb);
3596
3597
1/2
✓ Branch 0 taken 684 times.
✗ Branch 1 not taken.
684 built_query.add_array(drop_ctx.tmp_non_trans_tables_to_binlog);
3598 /*
3599 If there are no transactional temporary tables to be dropped
3600 add non-existent tables to this group. This ensures that on
3601 slave we won't split DROP TEMPORARY TABLES even if some tables
3602 are missing on it (which is no-no for GTID mode).
3603 */
3604
7/8
✓ Branch 0 taken 555 times.
✓ Branch 1 taken 129 times.
✓ Branch 2 taken 555 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 548 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 548 times.
✓ Branch 7 taken 136 times.
684 if (drop_ctx.drop_temporary && !drop_ctx.has_tmp_trans_tables())
3605
1/2
✓ Branch 0 taken 548 times.
✗ Branch 1 not taken.
548 built_query.add_array(drop_ctx.nonexistent_tables);
3606
3607 684 thd->thread_specific_used = true;
3608
3609
2/4
✓ Branch 0 taken 684 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 684 times.
684 if (built_query.write_bin_log()) goto err_with_rollback;
3610
3611
2/2
✓ Branch 0 taken 668 times.
✓ Branch 1 taken 16 times.
684 if (!drop_ctx.has_gtid_single_table_group()) {
3612 /*
3613 We don't have GTID assigned. If we are not inside of transaction
3614 commit transaction in binary log to get one for our statement.
3615 */
3616
5/6
✓ Branch 0 taken 668 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 577 times.
✓ Branch 3 taken 91 times.
✓ Branch 4 taken 577 times.
✓ Branch 5 taken 91 times.
668 if (mysql_bin_log.is_open() && !thd->in_active_multi_stmt_transaction()) {
3617 /*
3618 The single purpose of this hack is to generate GTID for the DROP
3619 TEMPORARY TABLES statement we just have written.
3620
3621 Some notes about it:
3622
3623 *) if the binary log is closed GTIDs are not generated, so there is
3624 no point in the below "commit".
3625 *) thd->in_active_multi_stmt_transaction() is true means that there
3626 is an active transaction with some changes to transactional tables
3627 and in binlog transactional cache. Doing "commit" in such a case
3628 will commit these changes in SE and flush binlog's cache to disk,
3629 so can not be allowed.
3630 OTOH, when thd->in_active_multi_stmt_transaction() false and
3631 thd->in_multi_stmt_transaction_mode() is true there is
3632 transaction from user's point of view. However there were no
3633 changes to transactional tables to commit (all changes were only
3634 to non-transactional tables) and nothing in binlog transactional
3635 cache (all changes to non-transactional tables were written to
3636 binlog directly). Calling "commit" in this case won't do anything
3637 besides generating GTID and can be allowed.
3638 *) We use MYSQL_BIN_LOG::commit() and not trans_commit_implicit(),
3639 for example, because we don't want to end user's explicitly
3640 started transaction.
3641 *) In theory we can allow to update slave info here by not raising
3642 THD::is_commit_in_middle_of_statement flag if we are in
3643 no-GTID-single-group case. However there is little benefit from
3644 it as dropping of temporary tables should not fail.
3645
3646 TODO: Consider if there is some better way to achieve this.
3647 For example, can we use trans_commit_implicit() to split
3648 out temporary parts from DROP TABLES statement or when
3649 splitting DROP TEMPORARY TABLES and there is no explicit
3650 user transaction. And just write two temporary parts
3651 to appropriate caches in case when DROP TEMPORARY is used
3652 inside of user's transaction?
3653 */
3654 577 thd->is_commit_in_middle_of_statement = true;
3655
1/2
✓ Branch 0 taken 577 times.
✗ Branch 1 not taken.
577 bool error = mysql_bin_log.commit(thd, true);
3656 577 thd->is_commit_in_middle_of_statement = false;
3657
3658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 577 times.
577 if (error) goto err_with_rollback;
3659 }
3660 } else {
3661 /*
3662 We have GTID assigned. Rely on commit at the end of statement or
3663 transaction to flush changes to binary log and mark GTID as executed.
3664 */
3665 }
3666
1/2
✓ Branch 0 taken 684 times.
✗ Branch 1 not taken.
684 }
3667
3668
3/4
✓ Branch 0 taken 154631 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 43647 times.
✓ Branch 3 taken 110984 times.
154631 if (drop_ctx.has_tmp_trans_tables()) {
3669
4/6
✓ Branch 0 taken 43647 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 43647 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43821 times.
✓ Branch 5 taken 43647 times.
87468 for (auto *table : drop_ctx.tmp_trans_tables) {
3670 /*
3671 Don't check THD::killed flag. We can't rollback deletion of
3672 temporary table, so aborting on KILL will make DROP TABLES
3673 less atomic.
3674 OTOH it is unlikely that we have many temporary tables to drop
3675 so being immune to KILL is not that horrible in most cases.
3676 */
3677
1/2
✓ Branch 0 taken 43821 times.
✗ Branch 1 not taken.
43821 drop_temporary_table(thd, table);
3678 }
3679
1/2
✓ Branch 0 taken 43647 times.
✗ Branch 1 not taken.
43647 thd->get_transaction()->mark_dropped_temp_table(Transaction_ctx::STMT);
3680 }
3681
3682
5/6
✓ Branch 0 taken 154631 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 153572 times.
✓ Branch 3 taken 1059 times.
✓ Branch 4 taken 1059 times.
✓ Branch 5 taken 153572 times.
308203 if (drop_ctx.has_tmp_trans_tables_to_binlog() ||
3683
3/4
✓ Branch 0 taken 153572 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 147969 times.
✓ Branch 3 taken 5603 times.
153572 (!drop_ctx.has_tmp_non_trans_tables() &&
3684
2/4
✓ Branch 0 taken 147969 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 147969 times.
147969 drop_ctx.has_tmp_nonexistent_tables())) {
3685 /*
3686 Handle transactional temporary tables (and possibly non-existent
3687 temporary tables if they were not handled earlier).
3688 */
3689
3690 /* DROP DATABASE doesn't deal with temporary tables. */
3691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1059 times.
1059 assert(!drop_ctx.drop_database);
3692
3693 /*
3694 If default database does not exist, set
3695 'is_drop_tmp_if_exists_with_no_defaultdb flag to 'true',
3696 so that the 'DROP TEMPORARY TABLE IF EXISTS' command is logged
3697 with a fully-qualified table name and we don't write "USE db"
3698 prefix.
3699
3700 If we are executing DROP TABLES (without TEMPORARY clause) we
3701 can't use binlog's trx cache, as it requires activetransaction
3702 with valid XID. Luckily, trx cache is not strictly necessary in
3703 this case and DROP TEMPORARY TABLES where it is really needed is
3704 exempted from this rule.
3705 */
3706 1059 const bool is_drop_tmp_if_exists_with_no_defaultdb =
3707
3/4
✓ Branch 0 taken 621 times.
✓ Branch 1 taken 438 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 621 times.
1059 (drop_ctx.if_exists && default_db_doesnt_exist);
3708
3709 Drop_tables_query_builder built_query(
3710 1059 thd, true /* DROP TEMPORARY */, drop_ctx.if_exists,
3711 1059 drop_ctx.drop_temporary /* trx/stmt cache */,
3712
1/2
✓ Branch 0 taken 1059 times.
✗ Branch 1 not taken.
1059 is_drop_tmp_if_exists_with_no_defaultdb);
3713
3714
1/2
✓ Branch 0 taken 1059 times.
✗ Branch 1 not taken.
1059 built_query.add_array(drop_ctx.tmp_trans_tables_to_binlog);
3715
3716 /*
3717 Add non-existent temporary tables to this group if there are some
3718 and they were not handled earlier.
3719 This ensures that on slave we won't split DROP TEMPORARY TABLES
3720 even if some tables are missing on it (which is no-no for GTID mode).
3721 */
3722
2/2
✓ Branch 0 taken 859 times.
✓ Branch 1 taken 200 times.
1059 if (drop_ctx.drop_temporary)
3723
1/2
✓ Branch 0 taken 859 times.
✗ Branch 1 not taken.
859 built_query.add_array(drop_ctx.nonexistent_tables);
3724
3725 1059 thd->thread_specific_used = true;
3726
3727
2/4
✓ Branch 0 taken 1059 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1059 times.
1059 if (built_query.write_bin_log()) goto err_with_rollback;
3728
3729
2/2
✓ Branch 0 taken 1034 times.
✓ Branch 1 taken 25 times.
1059 if (!drop_ctx.has_gtid_single_table_group()) {
3730 /*
3731 We don't have GTID assigned. If we are not inside of transaction
3732 commit transaction in binary log to get one for our statement.
3733 */
3734
5/6
✓ Branch 0 taken 1034 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 909 times.
✓ Branch 3 taken 125 times.
✓ Branch 4 taken 909 times.
✓ Branch 5 taken 125 times.
1034 if (mysql_bin_log.is_open() && !thd->in_active_multi_stmt_transaction()) {
3735 /*
3736 See the rationale for the hack with "commit" above.
3737 */
3738 909 thd->is_commit_in_middle_of_statement = true;
3739
1/2
✓ Branch 0 taken 909 times.
✗ Branch 1 not taken.
909 bool error = mysql_bin_log.commit(thd, true);
3740 909 thd->is_commit_in_middle_of_statement = false;
3741
3742
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 909 times.
909 if (error) goto err_with_rollback;
3743 }
3744 } else {
3745 /*
3746 We have GTID assigned. Rely on commit at the end of statement or
3747 transaction to flush changes to binary log and mark GTID as executed.
3748 */
3749 }
3750
1/2
✓ Branch 0 taken 1059 times.
✗ Branch 1 not taken.
1059 }
3751
3752
2/2
✓ Branch 0 taken 151442 times.
✓ Branch 1 taken 3189 times.
154631 if (!drop_ctx.drop_database) {
3753
3/4
✓ Branch 0 taken 62256 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 62258 times.
✓ Branch 3 taken 151440 times.
213698 for (handlerton *hton : *post_ddl_htons) hton->post_ddl(thd);
3754 }
3755
3756 154629 return false;
3757
3758 66 err_with_rollback:
3759
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 25 times.
66 if (!drop_ctx.drop_database) {
3760 /*
3761 Be consistent with successful case. Roll back statement
3762 and call post-DDL hooks within this function.
3763
3764 Note that this will rollback deletion of tables in SEs
3765 supporting atomic DDL only. Tables in engines which
3766 don't support atomic DDL are completely gone at this
3767 point.
3768 */
3769
3770
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 38 times.
44 if (drop_ctx.has_gtid_many_table_groups() &&
3771
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 drop_ctx.has_dropped_non_atomic()) {
3772 /*
3773 So far we have been postponing writing DROP TABLES statement for
3774 tables in engines not supporting atomic DDL. We are going to write
3775 it now and let it to consume GTID assigned. Hence rollback of
3776 tables deletion of in SEs supporting atomic DDL should not rollback
3777 GTID. Use guard class to disable this.
3778 */
3779
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 Implicit_substatement_state_guard substatement_guard(thd);
3780
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 trans_rollback_stmt(thd);
3781 /*
3782 Full rollback in case we have THD::transaction_rollback_request
3783 and to synchronize DD state in cache and on disk (as statement
3784 rollback doesn't clear DD cache of modified uncommitted objects).
3785 */
3786
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 trans_rollback(thd);
3787 3 } else {
3788
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 trans_rollback_stmt(thd);
3789 /*
3790 Full rollback in case we have THD::transaction_rollback_request
3791 and to synchronize DD state in cache and on disk (as statement
3792 rollback doesn't clear DD cache of modified uncommitted objects).
3793 */
3794
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 trans_rollback(thd);
3795 }
3796
3797
3/4
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 41 times.
72 for (handlerton *hton : *post_ddl_htons) hton->post_ddl(thd);
3798
3799
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 38 times.
44 if (drop_ctx.has_gtid_many_table_groups() &&
3800
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 drop_ctx.has_dropped_non_atomic()) {
3801 /*
3802 We have some tables dropped in SEs which don't support atomic DDL for
3803 which there were no binlog events written so far. Now we are going to
3804 write DROP TABLES statement for them and mark GTID as executed.
3805 This is not totally correct since original statement is only partially
3806 executed, but is consistent with 5.7 behavior.
3807
3808 TODO: Long-term we probably should generate new slave-based GTID for
3809 this event, or report special error about partial execution.
3810
3811 We don't have active transaction at this point so we can't use binlog's
3812 trx cache for this. It requires active transaction with valid XID.
3813
3814 */
3815 Drop_tables_query_builder built_query(
3816 3 thd, false /* no TEMPORARY */, drop_ctx.if_exists,
3817
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 false /* stmt cache*/, false /* db exists */);
3818
3819
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 built_query.add_array(drop_ctx.dropped_non_atomic);
3820
3821
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 (void)built_query.write_bin_log();
3822
3823 // Write statement to binary log and mark GTID as executed.
3824
3825 // We need to turn off updating of slave info
3826 // without conflicting with GTID update.
3827 {
3828 3 Disable_slave_info_update_guard substatement_guard(thd);
3829
3830
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 (void)trans_commit_stmt(thd);
3831
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 (void)trans_commit_implicit(thd);
3832 3 }
3833 3 }
3834 }
3835 66 return true;
3836 156462 }
3837
3838 /**
3839 Quickly remove a table.
3840
3841 @param thd Thread context.
3842 @param base The handlerton handle.
3843 @param db The database name.
3844 @param table_name The table name.
3845 @param flags Flags for build_table_filename().
3846
3847 @note In case when NO_DD_COMMIT flag was used, the caller must rollback
3848 both statement and transaction on failure. This is necessary to
3849 revert results of handler::ha_delete_table() call in case when
3850 update to the data-dictionary which follows it fails. Also this must
3851 be done before any further accesses to DD. @sa dd::drop_table().
3852
3853 @return False in case of success, True otherwise.
3854 */
3855
3856 19270 bool quick_rm_table(THD *thd, handlerton *base, const char *db,
3857 const char *table_name, uint flags) {
3858
1/2
✓ Branch 0 taken 19270 times.
✗ Branch 1 not taken.
19270 DBUG_TRACE;
3859
3860 // Build the schema qualified table name, to be submitted to the handler.
3861 char path[FN_REFLEN + 1];
3862
1/2
✓ Branch 0 taken 19270 times.
✗ Branch 1 not taken.
19270 (void)build_table_filename(path, sizeof(path) - 1, db, table_name, "", flags);
3863
3864 19270 const dd::Table *table_def = nullptr;
3865
4/8
✓ Branch 0 taken 19270 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19270 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19270 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 19270 times.
19270 if (thd->dd_client()->acquire(db, table_name, &table_def)) return true;
3866
3867 /* We try to remove non-existing tables in some scenarios. */
3868
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19270 times.
19270 if (!table_def) return false;
3869
3870
2/4
✓ Branch 0 taken 19256 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19256 times.
19270 if (ha_delete_table(thd, base, path, db, table_name, table_def, false))
3871 return true;
3872
3873 // Remove the table object from the data dictionary. If this fails, the
3874 // DD operation is already rolled back, and we must return with an error.
3875 // Note that the DD operation is done after invoking the SE. This is
3876 // because the DDL code will handle situations where a table is present
3877 // in the DD while missing from the SE, but not the opposite.
3878
5/10
✓ Branch 0 taken 19256 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19256 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19256 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 19256 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 19256 times.
✗ Branch 9 not taken.
19256 if (!dd::get_dictionary()->is_dd_table_name(db, table_name)) {
3879
1/2
✓ Branch 0 taken 19256 times.
✗ Branch 1 not taken.
19256 bool result = dd::drop_table(thd, db, table_name, *table_def);
3880
2/2
✓ Branch 0 taken 13072 times.
✓ Branch 1 taken 6184 times.
19256 if (!(flags & NO_DD_COMMIT))
3881
1/2
✓ Branch 0 taken 13072 times.
✗ Branch 1 not taken.
13072 result = trans_intermediate_ddl_commit(thd, result);
3882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19256 times.
19256 if (result) {
3883 assert(thd->is_error() || thd->killed);
3884 return true;
3885 }
3886 }
3887
3888 19256 return false;
3889 19256 }
3890
3891 /*
3892 Sort keys according to the following properties, in decreasing order of
3893 importance:
3894 - PRIMARY KEY
3895 - UNIQUE with all columns NOT NULL
3896 - UNIQUE without partial segments
3897 - UNIQUE
3898 - without fulltext columns
3899 - without virtual generated columns
3900
3901 This allows us to
3902 - check for duplicate key values faster (PK and UNIQUE are first)
3903 - prioritize PKs
3904 - be sure that, if there is no PK, the set of UNIQUE keys candidate for
3905 promotion starts at number 0, and we can choose #0 as PK (it is required
3906 that PK has number 0).
3907 */
3908
3909 namespace {
3910
3911 struct sort_keys {
3912 1771266 bool operator()(const KEY &a, const KEY &b) const {
3913 // Sort UNIQUE before not UNIQUE.
3914
2/2
✓ Branch 0 taken 727788 times.
✓ Branch 1 taken 1043478 times.
1771266 if ((a.flags ^ b.flags) & HA_NOSAME) return a.flags & HA_NOSAME;
3915
3916
2/2
✓ Branch 0 taken 771110 times.
✓ Branch 1 taken 272368 times.
1043478 if (a.flags & HA_NOSAME) {
3917 // Sort UNIQUE NOT NULL keys before other UNIQUE keys.
3918
2/2
✓ Branch 0 taken 89575 times.
✓ Branch 1 taken 681535 times.
771110 if ((a.flags ^ b.flags) & HA_NULL_PART_KEY)
3919 89575 return b.flags & HA_NULL_PART_KEY;
3920
3921 // Sort PRIMARY KEY before other UNIQUE NOT NULL.
3922
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 681492 times.
681535 if (a.name == primary_key_name) return true;
3923
2/2
✓ Branch 0 taken 543394 times.
✓ Branch 1 taken 138098 times.
681492 if (b.name == primary_key_name) return false;
3924
3925 // Sort keys don't containing partial segments before others.
3926
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 138055 times.
138098 if ((a.flags ^ b.flags) & HA_KEY_HAS_PART_KEY_SEG)
3927 43 return b.flags & HA_KEY_HAS_PART_KEY_SEG;
3928 }
3929
3930
2/2
✓ Branch 0 taken 150 times.
✓ Branch 1 taken 410273 times.
410423 if ((a.flags ^ b.flags) & HA_FULLTEXT) return b.flags & HA_FULLTEXT;
3931
3932
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 409953 times.
410273 if ((a.flags ^ b.flags) & HA_VIRTUAL_GEN_KEY)
3933 320 return b.flags & HA_VIRTUAL_GEN_KEY;
3934
3935 /*
3936 Prefer original key order. usable_key_parts contains here
3937 the original key position.
3938 */
3939 409953 return a.usable_key_parts < b.usable_key_parts;
3940 }
3941 };
3942
3943 } // namespace
3944
3945 /*
3946 Check TYPELIB (set or enum) for duplicates
3947
3948 SYNOPSIS
3949 check_duplicates_in_interval()
3950 thd Thread handle
3951 set_or_name "SET" or "ENUM" string for warning message
3952 name name of the checked column
3953 typelib list of values for the column
3954 dup_val_count returns count of duplicate elements
3955
3956 DESCRIPTION
3957 This function prints an warning for each value in list
3958 which has some duplicates on its right
3959
3960 RETURN VALUES
3961 0 ok
3962 1 Error
3963 */
3964
3965 897535 static bool check_duplicates_in_interval(THD *thd, const char *set_or_name,
3966 const char *name, TYPELIB *typelib,
3967 const CHARSET_INFO *cs,
3968 uint *dup_val_count) {
3969 897535 TYPELIB tmp = *typelib;
3970 897535 const char **cur_value = typelib->type_names;
3971 897535 unsigned int *cur_length = typelib->type_lengths;
3972 897535 *dup_val_count = 0;
3973
3974
2/2
✓ Branch 0 taken 4102091 times.
✓ Branch 1 taken 897524 times.
4999615 for (; tmp.count > 1; cur_value++, cur_length++) {
3975 4102091 tmp.type_names++;
3976 4102091 tmp.type_lengths++;
3977 4102091 tmp.count--;
3978
3/4
✓ Branch 0 taken 4102091 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✓ Branch 3 taken 4102042 times.
4102091 if (find_type2(&tmp, *cur_value, *cur_length, cs)) {
3979
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 ErrConvString err(*cur_value, *cur_length, cs);
3980
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 38 times.
49 if (thd->is_strict_mode()) {
3981
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0), name, err.ptr(),
3982 set_or_name);
3983 11 return true;
3984 }
3985
2/4
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
38 push_warning_printf(thd, Sql_condition::SL_NOTE,
3986 ER_DUPLICATED_VALUE_IN_TYPE,
3987 ER_THD(thd, ER_DUPLICATED_VALUE_IN_TYPE), name,
3988 err.ptr(), set_or_name);
3989 38 (*dup_val_count)++;
3990 }
3991 }
3992 897524 return false;
3993 }
3994
3995 /**
3996 Prepare a create_table instance for packing
3997
3998 @param thd Thread handle
3999 @param [in,out] sql_field field to prepare for packing
4000 @param table_flags table flags
4001
4002 @return true if error, false if ok
4003 */
4004
4005 6749923 bool prepare_pack_create_field(THD *thd, Create_field *sql_field,
4006 longlong table_flags) {
4007 unsigned int dup_val_count;
4008
1/2
✓ Branch 0 taken 6749939 times.
✗ Branch 1 not taken.
6749923 DBUG_TRACE;
4009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6749939 times.
6749939 assert(sql_field->charset);
4010
4011 6749939 sql_field->is_nullable = true;
4012 6749939 sql_field->is_zerofill = false;
4013 6749939 sql_field->is_unsigned = false;
4014
4015
8/8
✓ Branch 0 taken 2829 times.
✓ Branch 1 taken 997433 times.
✓ Branch 2 taken 1293565 times.
✓ Branch 3 taken 214379 times.
✓ Branch 4 taken 844079 times.
✓ Branch 5 taken 53456 times.
✓ Branch 6 taken 65502 times.
✓ Branch 7 taken 3278696 times.
6749939 switch (sql_field->sql_type) {
4016 2829 case MYSQL_TYPE_GEOMETRY:
4017
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2828 times.
2829 if (!(table_flags & HA_CAN_GEOMETRY)) {
4018
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "GEOMETRY");
4019 1 return true;
4020 }
4021 [[fallthrough]];
4022 case MYSQL_TYPE_BLOB:
4023 case MYSQL_TYPE_MEDIUM_BLOB:
4024 case MYSQL_TYPE_TINY_BLOB:
4025 case MYSQL_TYPE_LONG_BLOB:
4026 case MYSQL_TYPE_JSON:
4027
3/4
✓ Branch 0 taken 392 times.
✓ Branch 1 taken 999869 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 392 times.
1000261 assert(sql_field->auto_flags == Field::NONE ||
4028 sql_field->auto_flags == Field::GENERATED_FROM_EXPRESSION);
4029 1000261 break;
4030 1293565 case MYSQL_TYPE_VARCHAR:
4031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1293565 times.
1293565 if (table_flags & HA_NO_VARCHAR) {
4032 /* Convert VARCHAR to CHAR because handler is not yet up to date */
4033 sql_field->sql_type = MYSQL_TYPE_VAR_STRING;
4034 if (sql_field->max_display_width_in_codepoints() >
4035 MAX_FIELD_CHARLENGTH) {
4036 my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
4037 static_cast<ulong>(MAX_FIELD_CHARLENGTH));
4038 return true;
4039 }
4040 }
4041 1293565 break;
4042 214379 case MYSQL_TYPE_STRING:
4043 214379 break;
4044 844079 case MYSQL_TYPE_ENUM:
4045
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 844071 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
844079 assert(sql_field->auto_flags == Field::NONE ||
4046 sql_field->auto_flags == Field::GENERATED_FROM_EXPRESSION);
4047
3/4
✓ Branch 0 taken 844079 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 844075 times.
844079 if (check_duplicates_in_interval(thd, "ENUM", sql_field->field_name,
4048 sql_field->interval, sql_field->charset,
4049 &dup_val_count))
4050 4 return true;
4051
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 844074 times.
844075 if (sql_field->interval->count > MAX_ENUM_VALUES) {
4052
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_TOO_BIG_ENUM, MYF(0), sql_field->field_name);
4053 1 return true;
4054 }
4055 844074 break;
4056 53456 case MYSQL_TYPE_SET:
4057
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 53448 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
53456 assert(sql_field->auto_flags == Field::NONE ||
4058 sql_field->auto_flags == Field::GENERATED_FROM_EXPRESSION);
4059
3/4
✓ Branch 0 taken 53456 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 53449 times.
53456 if (check_duplicates_in_interval(thd, "SET", sql_field->field_name,
4060 sql_field->interval, sql_field->charset,
4061 &dup_val_count))
4062 7 return true;
4063 /* Check that count of unique members is not more then 64 */
4064
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 53445 times.
53449 if (sql_field->interval->count - dup_val_count > sizeof(longlong) * 8) {
4065
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_TOO_BIG_SET, MYF(0), sql_field->field_name);
4066 4 return true;
4067 }
4068 53445 break;
4069 65502 case MYSQL_TYPE_DATE: // Rest of string types
4070 case MYSQL_TYPE_NEWDATE:
4071 case MYSQL_TYPE_TIME:
4072 case MYSQL_TYPE_DATETIME:
4073 case MYSQL_TYPE_TIME2:
4074 case MYSQL_TYPE_DATETIME2:
4075 case MYSQL_TYPE_NULL:
4076 case MYSQL_TYPE_BIT:
4077 65502 break;
4078 3278696 case MYSQL_TYPE_TIMESTAMP:
4079 case MYSQL_TYPE_TIMESTAMP2:
4080 case MYSQL_TYPE_NEWDECIMAL:
4081 default:
4082
2/2
✓ Branch 0 taken 4453 times.
✓ Branch 1 taken 3274243 times.
3278696 if (sql_field->flags & ZEROFILL_FLAG) sql_field->is_zerofill = true;
4083
2/2
✓ Branch 0 taken 2116802 times.
✓ Branch 1 taken 1161894 times.
3278696 if (sql_field->flags & UNSIGNED_FLAG) sql_field->is_unsigned = true;
4084 3278696 break;
4085 }
4086
4087
2/2
✓ Branch 0 taken 4094346 times.
✓ Branch 1 taken 2655576 times.
6749922 if (sql_field->flags & NOT_NULL_FLAG) sql_field->is_nullable = false;
4088 // Array fields are JSON fields, so override pack length
4089 6749922 sql_field->pack_length_override =
4090
2/2
✓ Branch 0 taken 423 times.
✓ Branch 1 taken 6749499 times.
6749922 sql_field->is_array ? (4 + portable_sizeof_char_ptr) : 0;
4091
4092 6749922 return false;
4093 6749939 }
4094
4095 546871 TYPELIB *create_typelib(MEM_ROOT *mem_root, Create_field *field_def) {
4096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 546871 times.
546871 if (!field_def->interval_list.elements) return nullptr;
4097
4098 TYPELIB *result =
4099
1/2
✓ Branch 0 taken 546871 times.
✗ Branch 1 not taken.
546871 reinterpret_cast<TYPELIB *>(mem_root->Alloc(sizeof(TYPELIB)));
4100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 546871 times.
546871 if (!result) return nullptr;
4101
4102 546871 result->count = field_def->interval_list.elements;
4103 546871 result->name = "";
4104
4105 // Allocate type_names and type_lengths as one block.
4106 546871 size_t nbytes = (sizeof(char *) + sizeof(uint)) * (result->count + 1);
4107 546871 if (!(result->type_names =
4108
2/4
✓ Branch 0 taken 546871 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 546871 times.
546871 reinterpret_cast<const char **>(mem_root->Alloc(nbytes))))
4109 return nullptr;
4110
4111 546871 result->type_lengths =
4112 546871 reinterpret_cast<uint *>(result->type_names + result->count + 1);
4113
4114
1/2
✓ Branch 0 taken 546871 times.
✗ Branch 1 not taken.
546871 List_iterator<String> it(field_def->interval_list);
4115
2/2
✓ Branch 0 taken 4242977 times.
✓ Branch 1 taken 546871 times.
4789848 for (uint i = 0; i < result->count; i++) {
4116 size_t dummy;
4117 4242977 String *tmp = it++;
4118
4119
3/4
✓ Branch 0 taken 4242977 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3982766 times.
✓ Branch 3 taken 260211 times.
4242977 if (String::needs_conversion(tmp->length(), tmp->charset(),
4120 field_def->charset, &dummy)) {
4121 uint cnv_errs;
4122 3982766 String conv;
4123
1/2
✓ Branch 0 taken 3982766 times.
✗ Branch 1 not taken.
3982766 conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), field_def->charset,
4124 &cnv_errs);
4125
4126
1/2
✓ Branch 0 taken 3982766 times.
✗ Branch 1 not taken.
3982766 result->type_names[i] = strmake_root(mem_root, conv.ptr(), conv.length());
4127 3982766 result->type_lengths[i] = conv.length();
4128 3982766 } else {
4129 260211 result->type_names[i] = tmp->ptr();
4130 260211 result->type_lengths[i] = tmp->length();
4131 }
4132
4133 // Strip trailing spaces.
4134 8485954 size_t length = field_def->charset->cset->lengthsp(
4135
1/2
✓ Branch 0 taken 4242977 times.
✗ Branch 1 not taken.
4242977 field_def->charset, result->type_names[i], result->type_lengths[i]);
4136 4242977 result->type_lengths[i] = length;
4137 4242977 (const_cast<char *>(result->type_names[i]))[length] = '\0';
4138 }
4139 546871 result->type_names[result->count] = nullptr; // End marker (char*)
4140 546871 result->type_lengths[result->count] = 0; // End marker (uint)
4141
4142 546871 field_def->interval_list.clear(); // Don't need interval_list anymore
4143 546871 return result;
4144 }
4145
4146 /**
4147 Prepare an instance of Create_field for field creation
4148 (fill all necessary attributes). Only used for stored programs.
4149
4150 @param[in] thd Thread handle
4151 @param[out] field_def An instance of initialized create_field
4152
4153 @return Error status.
4154 */
4155
4156 371770 bool prepare_sp_create_field(THD *thd, Create_field *field_def) {
4157
2/2
✓ Branch 0 taken 617 times.
✓ Branch 1 taken 371153 times.
371770 if (field_def->sql_type == MYSQL_TYPE_SET) {
4158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 617 times.
617 if (prepare_set_field(thd, field_def)) return true;
4159
2/2
✓ Branch 0 taken 12625 times.
✓ Branch 1 taken 358528 times.
371153 } else if (field_def->sql_type == MYSQL_TYPE_ENUM) {
4160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12625 times.
12625 if (prepare_enum_field(thd, field_def)) return true;
4161
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 358464 times.
358528 } else if (field_def->sql_type == MYSQL_TYPE_BIT)
4162 64 field_def->treat_bit_as_char = true;
4163
4164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 371772 times.
371770 if (prepare_blob_field(thd, field_def, false)) return true;
4165
4166 371772 return prepare_pack_create_field(thd, field_def, HA_CAN_GEOMETRY);
4167 }
4168
4169 /**
4170 Get the character set from field object generated by the parser, using
4171 default values when not set.
4172
4173 @param sql_field The sql_field object
4174 @param create_info Info generated by parser
4175 @return character set
4176 */
4177 6416490 const CHARSET_INFO *get_sql_field_charset(const Create_field *sql_field,
4178 const HA_CREATE_INFO *create_info) {
4179
2/2
✓ Branch 0 taken 2188533 times.
✓ Branch 1 taken 4227957 times.
6416490 const CHARSET_INFO *cs = sql_field->charset != nullptr
4180 ? sql_field->charset
4181 : create_info->default_table_charset;
4182
4183 /*
4184 The hidden ARRAY typed column that backs the multi-valued index, and is
4185 implemented as a JSON column, can only use the character sets
4186 my_charset_utf8mb4_0900_bin or binary. This column's charset should not
4187 be changed when altering the table_charset.
4188 (See Field_typed_array for more details).
4189 Also table_charset must not affect the BLOB fields, so don't allow to change
4190 my_charset_bin to something else.
4191 */
4192
4/4
✓ Branch 0 taken 6416065 times.
✓ Branch 1 taken 425 times.
✓ Branch 2 taken 321657 times.
✓ Branch 3 taken 6094408 times.
6416490 if (sql_field->is_array || cs == &my_charset_bin) return cs;
4193
4194 /*
4195 table_charset is set only in ALTER TABLE t1 CONVERT TO CHARACTER SET csname
4196 when we want to change character set for all varchar/char columns.
4197 */
4198
2/2
✓ Branch 0 taken 20000 times.
✓ Branch 1 taken 6074408 times.
6094408 if (create_info->table_charset != nullptr) return create_info->table_charset;
4199
4200 6074408 return cs;
4201 }
4202
4203 /**
4204 Modifies the first column definition whose SQL type is TIMESTAMP
4205 by adding the features DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP.
4206
4207 @param column_definitions The list of column definitions, in the physical
4208 order in which they appear in the table.
4209 */
4210 197 void promote_first_timestamp_column(List<Create_field> *column_definitions) {
4211
1/2
✓ Branch 0 taken 197 times.
✗ Branch 1 not taken.
197 List_iterator<Create_field> it(*column_definitions);
4212 Create_field *column_definition;
4213
4214
2/2
✓ Branch 0 taken 298 times.
✓ Branch 1 taken 127 times.
425 while ((column_definition = it++) != nullptr) {
4215
2/2
✓ Branch 0 taken 292 times.
✓ Branch 1 taken 6 times.
298 if (column_definition->sql_type == MYSQL_TYPE_TIMESTAMP || // TIMESTAMP
4216
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 228 times.
292 column_definition->sql_type == MYSQL_TYPE_TIMESTAMP2) // ms TIMESTAMP
4217 {
4218
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 14 times.
70 if ((column_definition->flags & NOT_NULL_FLAG) != 0 && // NOT NULL,
4219
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 19 times.
56 column_definition->constant_default ==
4220 37 nullptr && // no constant default
4221
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 column_definition->gcol_info == nullptr && // not a generated column
4222
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 22 times.
37 column_definition->auto_flags == Field::NONE) // no function default
4223 {
4224
3/8
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
15 DBUG_PRINT("info", ("First TIMESTAMP column '%s' was promoted to "
4225 "DEFAULT CURRENT_TIMESTAMP ON UPDATE "
4226 "CURRENT_TIMESTAMP",
4227 column_definition->field_name));
4228 15 column_definition->auto_flags =
4229 Field::DEFAULT_NOW | Field::ON_UPDATE_NOW;
4230 }
4231 70 return;
4232 }
4233 }
4234 }
4235
4236 /**
4237 Check if there is a duplicate key. Report a warning for every duplicate key.
4238
4239 @param thd Thread context.
4240 @param error_schema_name Schema name of the table used for error reporting.
4241 @param error_table_name Table name used for error reporting.
4242 @param key Key to be checked.
4243 @param key_info Array with all keys for the table.
4244 @param key_count Number of keys in the table.
4245 @param alter_info Alter_info structure describing ALTER TABLE.
4246
4247 @note Unlike has_index_def_changed() and similar code in
4248 mysql_compare_tables() this function compares KEY objects for the same
4249 table/created by the same mysql_prepare_create(). Hence difference in
4250 field number comparison. We also differentiate UNIQUE and PRIMARY keys.
4251
4252 @retval false Ok.
4253 @retval true Error.
4254 */
4255 929338 static bool check_duplicate_key(THD *thd, const char *error_schema_name,
4256 const char *error_table_name, const KEY *key,
4257 const KEY *key_info, uint key_count,
4258 Alter_info *alter_info) {
4259 const KEY *k;
4260 929338 const KEY *k_end = key_info + key_count;
4261
4262 /* This function should not be called for PRIMARY or generated keys. */
4263
2/4
✓ Branch 0 taken 929338 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 929338 times.
✗ Branch 3 not taken.
929338 assert(key->name != primary_key_name && !(key->flags & HA_GENERATED_KEY));
4264
4265
2/2
✓ Branch 0 taken 3167555 times.
✓ Branch 1 taken 103 times.
3167658 for (k = key_info; k != k_end; k++) {
4266 // Looking for a similar key...
4267
4268
2/2
✓ Branch 0 taken 928962 times.
✓ Branch 1 taken 2238593 times.
3167555 if (k == key) {
4269 /*
4270 Since the duplicate index might exist before or after
4271 the modified key in the list, we continue the
4272 comparison with rest of the keys in case of DROP COLUMN
4273 operation.
4274 */
4275
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 928851 times.
928962 if (alter_info->flags & Alter_info::ALTER_DROP_COLUMN)
4276 111 continue;
4277 else
4278 928851 break;
4279 }
4280
4281 /*
4282 Treat key as not duplicate if:
4283 - it is generated (as it will be automagically removed if duplicate later)
4284 - has different type (Instead of differentiating between PRIMARY and
4285 UNIQUE keys we simply skip check for PRIMARY keys. The fact that we
4286 have only one primary key for the table is checked elsewhere.)
4287 - has different algorithm
4288 - has different number of key parts
4289 */
4290
2/2
✓ Branch 0 taken 2238152 times.
✓ Branch 1 taken 441 times.
2238593 if ((k->flags & HA_GENERATED_KEY) ||
4291
2/2
✓ Branch 0 taken 1136950 times.
✓ Branch 1 taken 1101202 times.
2238152 ((key->flags & HA_KEYFLAG_MASK) != (k->flags & HA_KEYFLAG_MASK)) ||
4292
4/4
✓ Branch 0 taken 782681 times.
✓ Branch 1 taken 354269 times.
✓ Branch 2 taken 782675 times.
✓ Branch 3 taken 6 times.
1136950 (k->name == primary_key_name) || (key->algorithm != k->algorithm) ||
4293
2/2
✓ Branch 0 taken 167237 times.
✓ Branch 1 taken 615438 times.
782675 (key->user_defined_key_parts != k->user_defined_key_parts)) {
4294 // Keys are different.
4295 1623155 continue;
4296 }
4297
4298 /*
4299 Keys 'key' and 'k' might be identical.
4300 Check that the keys have identical columns in the same order.
4301 */
4302 const KEY_PART_INFO *key_part;
4303 615438 const KEY_PART_INFO *key_part_end =
4304 615438 key->key_part + key->user_defined_key_parts;
4305 const KEY_PART_INFO *k_part;
4306 615438 bool all_columns_are_identical = true;
4307
4308 615438 for (key_part = key->key_part, k_part = k->key_part;
4309
2/2
✓ Branch 0 taken 629779 times.
✓ Branch 1 taken 384 times.
630163 key_part < key_part_end; key_part++, k_part++) {
4310 /*
4311 Key definition is different if we are using a different field,
4312 if the used key part length is different or key parts has different
4313 direction. Note since both KEY objects come from
4314 mysql_prepare_create_table() we can compare field numbers directly.
4315 */
4316
2/2
✓ Branch 0 taken 299504 times.
✓ Branch 1 taken 330275 times.
629779 if ((key_part->length != k_part->length) ||
4317
2/2
✓ Branch 0 taken 14736 times.
✓ Branch 1 taken 284768 times.
299504 (key_part->fieldnr != k_part->fieldnr) ||
4318
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 14725 times.
14736 (key_part->key_part_flag != k_part->key_part_flag)) {
4319 615054 all_columns_are_identical = false;
4320 615054 break;
4321 }
4322 }
4323
4324 // Report a warning if we have two identical keys.
4325
4326
2/2
✓ Branch 0 taken 384 times.
✓ Branch 1 taken 615054 times.
615438 if (all_columns_are_identical) {
4327 384 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_DUP_INDEX,
4328 384 ER_THD(thd, ER_DUP_INDEX), key->name,
4329 error_schema_name, error_table_name);
4330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 if (thd->is_error()) {
4331 // An error was reported.
4332 return true;
4333 }
4334 384 break;
4335 }
4336 }
4337 929338 return false;
4338 }
4339
4340 /**
4341 Check if there is a collation change from the old field to the new
4342 create field. If so, scan the indexes of the new table (including
4343 the added ones), and check if the field is referred by any index.
4344
4345 @param field Field in old table.
4346 @param new_field Field in new table (create field).
4347 @param ha_alter_info Alter inplace info structure.
4348
4349 @retval true Field changes collation, and is indexed.
4350 @retval false Otherwise.
4351 */
4352 458 static bool is_collation_change_for_indexed_field(
4353 const Field &field, const Create_field &new_field,
4354 Alter_inplace_info *ha_alter_info) {
4355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 458 times.
458 assert(new_field.field == &field);
4356
4357 // No need to check indexes if the collation stays the same.
4358
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 394 times.
458 if (field.charset() == new_field.charset) return false;
4359
4360 394 const KEY *new_key_end =
4361 394 ha_alter_info->key_info_buffer + ha_alter_info->key_count;
4362 422 for (const KEY *new_key = ha_alter_info->key_info_buffer;
4363
2/2
✓ Branch 0 taken 356 times.
✓ Branch 1 taken 66 times.
422 new_key < new_key_end; new_key++) {
4364 /*
4365 If the key of the new table has a part which referring to the create
4366 field submitted, then mark this as a change of the stored column type.
4367 This will prohibit performing this as an inplace operation.
4368 */
4369 356 const KEY_PART_INFO *end =
4370 356 new_key->key_part + new_key->user_defined_key_parts;
4371
2/2
✓ Branch 0 taken 1305 times.
✓ Branch 1 taken 28 times.
1333 for (const KEY_PART_INFO *new_part = new_key->key_part; new_part < end;
4372 new_part++) {
4373
2/2
✓ Branch 0 taken 328 times.
✓ Branch 1 taken 977 times.
1305 if (get_field_by_index(ha_alter_info->alter_info, new_part->fieldnr) ==
4374 &new_field)
4375 328 return true;
4376 }
4377 }
4378
4379 66 return false;
4380 }
4381
4382 /**
4383 Helper function which allows to detect column types for which we historically
4384 used key packing (optimization implemented only by MyISAM) under erroneous
4385 assumption that they have BLOB type.
4386 */
4387 16236 static bool is_phony_blob(enum_field_types sql_type, uint decimals) {
4388 16236 const uint FIELDFLAG_BLOB = 1024;
4389 16236 const uint FIELDFLAG_DEC_SHIFT = 8;
4390
4391
3/4
✓ Branch 0 taken 16222 times.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16222 times.
16236 return (sql_type == MYSQL_TYPE_NEWDECIMAL || sql_type == MYSQL_TYPE_DOUBLE ||
4392
1/2
✓ Branch 0 taken 16236 times.
✗ Branch 1 not taken.
32472 sql_type == MYSQL_TYPE_DECIMAL) &&
4393
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
16250 (((decimals << FIELDFLAG_DEC_SHIFT) & FIELDFLAG_BLOB) != 0);
4394 }
4395
4396 53465 static bool prepare_set_field(THD *thd, Create_field *sql_field) {
4397
1/2
✓ Branch 0 taken 53465 times.
✗ Branch 1 not taken.
53465 DBUG_TRACE;
4398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53465 times.
53465 assert(sql_field->sql_type == MYSQL_TYPE_SET);
4399
4400 /*
4401 Create typelib from interval_list, and if necessary
4402 convert strings from client character set to the
4403 column character set.
4404 */
4405
2/2
✓ Branch 0 taken 45965 times.
✓ Branch 1 taken 7500 times.
53465 if (!sql_field->interval) {
4406 /*
4407 Create the typelib in runtime memory - we will free the
4408 occupied memory at the same time when we free this
4409 sql_field -- at the end of execution.
4410 */
4411
1/2
✓ Branch 0 taken 45965 times.
✗ Branch 1 not taken.
45965 sql_field->interval = create_typelib(thd->mem_root, sql_field);
4412 }
4413
4414 // Comma is an invalid character for SET names
4415 char comma_buf[4]; /* 4 bytes for utf32 */
4416
1/2
✓ Branch 0 taken 53465 times.
✗ Branch 1 not taken.
53465 int comma_length = sql_field->charset->cset->wc_mb(
4417 sql_field->charset, ',', reinterpret_cast<uchar *>(comma_buf),
4418 reinterpret_cast<uchar *>(comma_buf) + sizeof(comma_buf));
4419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53465 times.
53465 assert(comma_length > 0);
4420
4421
2/2
✓ Branch 0 taken 1263764 times.
✓ Branch 1 taken 53464 times.
1317228 for (uint i = 0; i < sql_field->interval->count; i++) {
4422
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1263763 times.
1263764 if (sql_field->charset->coll->strstr(sql_field->charset,
4423 1263764 sql_field->interval->type_names[i],
4424
1/2
✓ Branch 0 taken 1263764 times.
✗ Branch 1 not taken.
1263764 sql_field->interval->type_lengths[i],
4425 comma_buf, comma_length, nullptr, 0)) {
4426 1 ErrConvString err(sql_field->interval->type_names[i],
4427 1 sql_field->interval->type_lengths[i],
4428
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 sql_field->charset);
4429
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", err.ptr());
4430 1 return true;
4431 }
4432 }
4433
4434
2/2
✓ Branch 0 taken 8259 times.
✓ Branch 1 taken 45205 times.
53464 if (sql_field->constant_default != nullptr) {
4435 const char *not_used;
4436 uint not_used2;
4437 8259 bool not_found = false;
4438 8259 String str;
4439
1/2
✓ Branch 0 taken 8259 times.
✗ Branch 1 not taken.
8259 String *def = sql_field->constant_default->val_str(&str);
4440
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8256 times.
8259 if (def == nullptr) /* SQL "NULL" maps to NULL */
4441 {
4442
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if ((sql_field->flags & NOT_NULL_FLAG) != 0) {
4443
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
4444 1 return true;
4445 }
4446
4447 /* else, NULL is an allowed value */
4448
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 (void)find_set(sql_field->interval, nullptr, 0, sql_field->charset,
4449 &not_used, &not_used2, &not_found);
4450 } else /* not NULL */
4451 {
4452
1/2
✓ Branch 0 taken 8256 times.
✗ Branch 1 not taken.
8256 (void)find_set(sql_field->interval, def->ptr(), def->length(),
4453 sql_field->charset, &not_used, &not_used2, &not_found);
4454 }
4455
4456
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 8251 times.
8258 if (not_found) {
4457
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
4458 7 return true;
4459 }
4460
2/2
✓ Branch 0 taken 8251 times.
✓ Branch 1 taken 8 times.
8259 }
4461
4462 53456 return false;
4463 53465 }
4464
4465 848359 static bool prepare_enum_field(THD *thd, Create_field *sql_field) {
4466
1/2
✓ Branch 0 taken 848359 times.
✗ Branch 1 not taken.
848359 DBUG_TRACE;
4467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 848359 times.
848359 assert(sql_field->sql_type == MYSQL_TYPE_ENUM);
4468
4469 /*
4470 Create typelib from interval_list, and if necessary
4471 convert strings from client character set to the
4472 column character set.
4473 */
4474
2/2
✓ Branch 0 taken 500906 times.
✓ Branch 1 taken 347453 times.
848359 if (!sql_field->interval) {
4475 /*
4476 Create the typelib in runtime memory - we will free the
4477 occupied memory at the same time when we free this
4478 sql_field -- at the end of execution.
4479 */
4480
1/2
✓ Branch 0 taken 500906 times.
✗ Branch 1 not taken.
500906 sql_field->interval = create_typelib(thd->mem_root, sql_field);
4481 }
4482
4483
2/2
✓ Branch 0 taken 369837 times.
✓ Branch 1 taken 478522 times.
848359 if (sql_field->constant_default != nullptr) {
4484 369837 String str;
4485
1/2
✓ Branch 0 taken 369837 times.
✗ Branch 1 not taken.
369837 String *def = sql_field->constant_default->val_str(&str);
4486
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 369834 times.
369837 if (def == nullptr) /* SQL "NULL" maps to NULL */
4487 {
4488
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if ((sql_field->flags & NOT_NULL_FLAG) != 0) {
4489
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
4490 1 return true;
4491 }
4492
4493 /* else, the defaults yield the correct length for NULLs. */
4494 } else /* not NULL */
4495 {
4496
1/2
✓ Branch 0 taken 369834 times.
✗ Branch 1 not taken.
739668 def->length(sql_field->charset->cset->lengthsp(
4497 369834 sql_field->charset, def->ptr(), def->length()));
4498
1/2
✓ Branch 0 taken 369834 times.
✗ Branch 1 not taken.
369834 if (find_type2(sql_field->interval, def->ptr(), def->length(),
4499
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 369828 times.
369834 sql_field->charset) == 0) /* not found */
4500 {
4501
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
4502 6 return true;
4503 }
4504 }
4505
2/2
✓ Branch 0 taken 369830 times.
✓ Branch 1 taken 7 times.
369837 }
4506
4507 848352 return false;
4508 848359 }
4509
4510 6385553 bool prepare_create_field(THD *thd, const char *error_schema_name,
4511 const char *error_table_name,
4512 HA_CREATE_INFO *create_info,
4513 List<Create_field> *create_list,
4514 int *select_field_pos, handler *file,
4515 Create_field *sql_field, int field_no) {
4516
1/2
✓ Branch 0 taken 6385562 times.
✗ Branch 1 not taken.
6385553 DBUG_TRACE;
4517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6385562 times.
6385562 assert(create_list);
4518 const CHARSET_INFO *save_cs;
4519
4520 /* Set field charset. */
4521
1/2
✓ Branch 0 taken 6385558 times.
✗ Branch 1 not taken.
6385562 save_cs = sql_field->charset = get_sql_field_charset(sql_field, create_info);
4522
4523
2/2
✓ Branch 0 taken 6853 times.
✓ Branch 1 taken 6378705 times.
6385558 if (sql_field->flags & BINCMP_FLAG) {
4524 // e.g. CREATE TABLE t1 (a CHAR(1) BINARY);
4525
2/4
✓ Branch 0 taken 6853 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6853 times.
6853 if (!(sql_field->charset = get_charset_by_csname(sql_field->charset->csname,
4526 MY_CS_BINSORT, MYF(0)))) {
4527 char tmp[65];
4528 strmake(strmake(tmp, save_cs->csname, sizeof(tmp) - 4),
4529 STRING_WITH_LEN("_bin"));
4530 my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
4531 return true;
4532 }
4533 /*
4534 Now that we have sql_field->charset set properly,
4535 we don't need the BINCMP_FLAG any longer.
4536 */
4537 6853 sql_field->flags &= ~BINCMP_FLAG;
4538 }
4539
4540 /*
4541 Convert the default value from client character
4542 set into the column character set if necessary.
4543 */
4544
2/2
✓ Branch 0 taken 582199 times.
✓ Branch 1 taken 5803359 times.
6385558 if (sql_field->constant_default &&
4545
2/2
✓ Branch 0 taken 108424 times.
✓ Branch 1 taken 473775 times.
582199 save_cs != sql_field->constant_default->collation.collation &&
4546
1/2
✓ Branch 0 taken 108424 times.
✗ Branch 1 not taken.
108424 (sql_field->sql_type == MYSQL_TYPE_VAR_STRING ||
4547
2/2
✓ Branch 0 taken 83572 times.
✓ Branch 1 taken 24852 times.
108424 sql_field->sql_type == MYSQL_TYPE_STRING ||
4548
2/2
✓ Branch 0 taken 81102 times.
✓ Branch 1 taken 2470 times.
83572 sql_field->sql_type == MYSQL_TYPE_SET ||
4549
2/2
✓ Branch 0 taken 39026 times.
✓ Branch 1 taken 42076 times.
81102 sql_field->sql_type == MYSQL_TYPE_ENUM)) {
4550 /*
4551 Starting from 5.1 we work here with a copy of Create_field
4552 created by the caller, not with the instance that was
4553 originally created during parsing. It's OK to create
4554 a temporary item and initialize with it a member of the
4555 copy -- this item will be thrown away along with the copy
4556 at the end of execution, and thus not introduce a dangling
4557 pointer in the parsed tree of a prepared statement or a
4558 stored procedure statement.
4559 */
4560 66346 sql_field->constant_default =
4561
1/2
✓ Branch 0 taken 66346 times.
✗ Branch 1 not taken.
66348 sql_field->constant_default->safe_charset_converter(thd, save_cs);
4562
4563
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 66345 times.
66346 if (sql_field->constant_default == nullptr) {
4564 /* Could not convert */
4565
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
4566 1 return true;
4567 }
4568 }
4569
4570
2/2
✓ Branch 0 taken 52848 times.
✓ Branch 1 taken 6332707 times.
6385555 if (sql_field->sql_type == MYSQL_TYPE_SET) {
4571
3/4
✓ Branch 0 taken 52848 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 52839 times.
52848 if (prepare_set_field(thd, sql_field)) return true;
4572
2/2
✓ Branch 0 taken 835734 times.
✓ Branch 1 taken 5496973 times.
6332707 } else if (sql_field->sql_type == MYSQL_TYPE_ENUM) {
4573
3/4
✓ Branch 0 taken 835734 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 835727 times.
835734 if (prepare_enum_field(thd, sql_field)) return true;
4574
2/2
✓ Branch 0 taken 2554 times.
✓ Branch 1 taken 5494419 times.
5496973 } else if (sql_field->sql_type == MYSQL_TYPE_BIT) {
4575
2/2
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 2308 times.
2554 if (file->ha_table_flags() & HA_CAN_BIT_FIELD) {
4576 246 create_info->null_bits +=
4577
1/2
✓ Branch 0 taken 246 times.
✗ Branch 1 not taken.
246 sql_field->max_display_width_in_codepoints() & 7;
4578 246 sql_field->treat_bit_as_char = false;
4579 } else
4580 2308 sql_field->treat_bit_as_char = true;
4581 }
4582
4583 6385539 bool convert_to_character_set =
4584 6385539 (create_info->used_fields & HA_CREATE_USED_CHARSET);
4585
3/4
✓ Branch 0 taken 6385540 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 6385531 times.
6385539 if (prepare_blob_field(thd, sql_field, convert_to_character_set)) {
4586 9 return true;
4587 }
4588
4589
2/2
✓ Branch 0 taken 2284990 times.
✓ Branch 1 taken 4100541 times.
6385531 if (!(sql_field->flags & NOT_NULL_FLAG)) create_info->null_bits++;
4590
4591
3/4
✓ Branch 0 taken 6385534 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 6385531 times.
6385531 if (check_column_name(sql_field->field_name)) {
4592
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
4593 3 return true;
4594 }
4595
4596 // Validate field comment string
4597 6385531 std::string invalid_sub_str;
4598 12771050 if (is_invalid_string(
4599
3/4
✓ Branch 0 taken 6385519 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6385517 times.
6385531 LEX_CSTRING{sql_field->comment.str, sql_field->comment.length},
4600 system_charset_info, invalid_sub_str)) {
4601 // Provide contextual information
4602
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 std::string qualified_field_name = std::string(error_schema_name) + "." +
4603
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
8 std::string(error_table_name) + "." +
4604
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
6 std::string(sql_field->field_name);
4605
4606
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_COMMENT_CONTAINS_INVALID_STRING, MYF(0), "field",
4607 qualified_field_name.c_str(), system_charset_info->csname,
4608 invalid_sub_str.c_str());
4609 2 return true;
4610 2 }
4611
4612
3/4
✓ Branch 0 taken 6385530 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 6385523 times.
6385517 if (validate_comment_length(thd, sql_field->comment.str,
4613 &sql_field->comment.length, COLUMN_COMMENT_MAXLEN,
4614 ER_TOO_LONG_FIELD_COMMENT, sql_field->field_name))
4615 7 return true;
4616
4617 // If this column has an SRID specified, check if the SRID actually exists
4618 // in the data dictionary.
4619
7/8
✓ Branch 0 taken 1636 times.
✓ Branch 1 taken 6383888 times.
✓ Branch 2 taken 1636 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 187 times.
✓ Branch 5 taken 1449 times.
✓ Branch 6 taken 187 times.
✓ Branch 7 taken 6385337 times.
6385523 if (sql_field->m_srid.has_value() && sql_field->m_srid.value() != 0) {
4620 187 bool exists = false;
4621
3/6
✓ Branch 0 taken 187 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 187 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 187 times.
187 if (Srs_fetcher::srs_exists(thd, sql_field->m_srid.value(), &exists)) {
4622 // An error has already been raised
4623 4 return true; /* purecov: deadcode */
4624 }
4625
4626
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 183 times.
187 if (!exists) {
4627
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 my_error(ER_SRS_NOT_FOUND, MYF(0), sql_field->m_srid.value());
4628 4 return true;
4629 }
4630 }
4631
4632 /* Check if we have used the same field name before */
4633 Create_field *dup_field;
4634
1/2
✓ Branch 0 taken 6385519 times.
✗ Branch 1 not taken.
6385520 List_iterator<Create_field> it(*create_list);
4635
2/2
✓ Branch 0 taken 105064709 times.
✓ Branch 1 taken 6376618 times.
111441340 for (int dup_no = 0; (dup_field = it++) != sql_field; dup_no++) {
4636
1/2
✓ Branch 0 taken 105064709 times.
✗ Branch 1 not taken.
105064709 if (my_strcasecmp(system_charset_info, sql_field->field_name,
4637
2/2
✓ Branch 0 taken 8889 times.
✓ Branch 1 taken 105055820 times.
105064709 dup_field->field_name) == 0) {
4638 /*
4639 If this was a CREATE ... SELECT statement, accept a field
4640 redefinition if we are changing a field in the SELECT part
4641 */
4642
4/4
✓ Branch 0 taken 1539 times.
✓ Branch 1 taken 7350 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1535 times.
8889 if (field_no < (*select_field_pos) || dup_no >= (*select_field_pos)) {
4643 // If one of the columns is a functional index column, but not both,
4644 // return an error saying that the column name is in use. The reason we
4645 // only raise an error if one, but not both, is a functional index
4646 // column, is that we want to report a "duplicate key name"-error if the
4647 // user renames a functional index to an existing functional index name:
4648 //
4649 // CREATE TABLE t1 (
4650 // col1 INT
4651 // , INDEX idx ((col1 + 1))
4652 // , INDEX idx2 ((col1 + 2)));
4653 //
4654 // ALTER TABLE t1 RENAME INDEX idx TO idx2;
4655 //
4656 // Note that duplicate names for regular indexes are detected later, so
4657 // we don't bother checking those here.
4658
1/2
✓ Branch 0 taken 7354 times.
✗ Branch 1 not taken.
7354 if ((is_field_for_functional_index(dup_field) !=
4659
3/4
✓ Branch 0 taken 7354 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7352 times.
7354 is_field_for_functional_index(sql_field))) {
4660 2 std::string error_description;
4661
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 error_description.append("The column name '");
4662
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 error_description.append(sql_field->field_name);
4663
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 error_description.append("' is already in use by a hidden column");
4664
4665
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_INTERNAL_ERROR, MYF(0), error_description.c_str());
4666 2 return true;
4667 2 }
4668
4669
5/6
✓ Branch 0 taken 7352 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7351 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 7351 times.
✓ Branch 5 taken 1 times.
14703 if (!is_field_for_functional_index(dup_field) &&
4670
2/4
✓ Branch 0 taken 7351 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7351 times.
✗ Branch 3 not taken.
7351 !is_field_for_functional_index(sql_field)) {
4671
1/2
✓ Branch 0 taken 7351 times.
✗ Branch 1 not taken.
7351 my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
4672 7351 return true;
4673 }
4674 1 } else {
4675 /* Field redefined */
4676
4677 /*
4678 If we are replacing a BIT field, revert the increment
4679 of null_bits that was done above.
4680 */
4681
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1535 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1535 times.
1535 if (sql_field->sql_type == MYSQL_TYPE_BIT &&
4682 file->ha_table_flags() & HA_CAN_BIT_FIELD) {
4683 create_info->null_bits -=
4684 sql_field->max_display_width_in_codepoints() & 7;
4685 }
4686
4687 1535 sql_field->constant_default = dup_field->constant_default;
4688 1535 sql_field->sql_type = dup_field->sql_type;
4689
4690 /*
4691 If we are replacing a field with a BIT field, we need
4692 to initialize treat_bit_as_char. Note that we do not need to
4693 increment null_bits here as this dup_field
4694 has already been processed.
4695 */
4696
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1534 times.
1535 if (sql_field->sql_type == MYSQL_TYPE_BIT) {
4697 1 sql_field->treat_bit_as_char =
4698 1 !(file->ha_table_flags() & HA_CAN_BIT_FIELD);
4699 }
4700
4701 1535 sql_field->charset =
4702
1/2
✓ Branch 0 taken 1535 times.
✗ Branch 1 not taken.
1535 (dup_field->charset ? dup_field->charset
4703 : create_info->default_table_charset);
4704
1/2
✓ Branch 0 taken 1535 times.
✗ Branch 1 not taken.
1535 sql_field->set_max_display_width_from_create_field(*dup_field);
4705 1535 sql_field->decimals = dup_field->decimals;
4706 1535 sql_field->auto_flags = dup_field->auto_flags;
4707 /*
4708 We're making one field from two, the result field will have
4709 dup_field->flags as flags. If we've incremented null_bits
4710 because of sql_field->flags, decrement it back.
4711 */
4712
2/2
✓ Branch 0 taken 1193 times.
✓ Branch 1 taken 342 times.
1535 if (!(sql_field->flags & NOT_NULL_FLAG)) create_info->null_bits--;
4713
4714 1535 sql_field->flags = dup_field->flags;
4715 1535 sql_field->interval = dup_field->interval;
4716 1535 sql_field->gcol_info = dup_field->gcol_info;
4717 1535 sql_field->m_default_val_expr = dup_field->m_default_val_expr;
4718 1535 sql_field->stored_in_db = dup_field->stored_in_db;
4719 1535 sql_field->hidden = dup_field->hidden;
4720
1/2
✓ Branch 0 taken 1535 times.
✗ Branch 1 not taken.
1535 it.remove(); // Remove first (create) definition
4721 1535 (*select_field_pos)--;
4722 1535 break;
4723 }
4724 }
4725 }
4726
4727 /* Don't pack rows in old tables if the user has requested this */
4728
2/2
✓ Branch 0 taken 5478421 times.
✓ Branch 1 taken 899732 times.
6378153 if ((sql_field->flags & BLOB_FLAG) ||
4729
2/2
✓ Branch 0 taken 1171400 times.
✓ Branch 1 taken 4307021 times.
5478421 (sql_field->sql_type == MYSQL_TYPE_VARCHAR &&
4730
2/2
✓ Branch 0 taken 1171393 times.
✓ Branch 1 taken 7 times.
1171400 create_info->row_type != ROW_TYPE_FIXED))
4731 2071125 create_info->table_options |= HA_OPTION_PACK_RECORD;
4732
4733
3/4
✓ Branch 0 taken 6378167 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 6378150 times.
6378153 if (prepare_pack_create_field(thd, sql_field, file->ha_table_flags()))
4734 17 return true;
4735
4736 6378150 return false;
4737 6385562 }
4738
4739 749478 static void calculate_field_offsets(List<Create_field> *create_list) {
4740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 749478 times.
749478 assert(create_list);
4741
1/2
✓ Branch 0 taken 749487 times.
✗ Branch 1 not taken.
749478 List_iterator<Create_field> it(*create_list);
4742 749487 size_t record_offset = 0;
4743 749487 bool has_vgc = false;
4744 Create_field *sql_field;
4745
2/2
✓ Branch 0 taken 6142805 times.
✓ Branch 1 taken 749488 times.
6892279 while ((sql_field = it++)) {
4746 6142805 sql_field->offset = record_offset;
4747 /*
4748 For now skip fields that are not physically stored in the database
4749 (generated fields) and update their offset later (see the next loop).
4750 */
4751
2/2
✓ Branch 0 taken 6132410 times.
✓ Branch 1 taken 10395 times.
6142805 if (sql_field->stored_in_db)
4752
1/2
✓ Branch 0 taken 6132397 times.
✗ Branch 1 not taken.
6132410 record_offset += sql_field->pack_length();
4753 else
4754 10395 has_vgc = true;
4755 }
4756 /* Update generated fields' offset*/
4757
2/2
✓ Branch 0 taken 5932 times.
✓ Branch 1 taken 743556 times.
749488 if (has_vgc) {
4758 5932 it.rewind();
4759
2/2
✓ Branch 0 taken 31554 times.
✓ Branch 1 taken 5932 times.
37486 while ((sql_field = it++)) {
4760
2/2
✓ Branch 0 taken 10395 times.
✓ Branch 1 taken 21159 times.
31554 if (!sql_field->stored_in_db) {
4761 10395 sql_field->offset = record_offset;
4762
1/2
✓ Branch 0 taken 10395 times.
✗ Branch 1 not taken.
10395 record_offset += sql_field->pack_length();
4763 }
4764 }
4765 }
4766 749488 }
4767
4768 /**
4769 Count keys and key segments. Note that FKs are ignored.
4770 Also mark redundant keys to be ignored.
4771
4772 @param[in,out] key_list List of keys to count and possibly mark as ignored.
4773 @param[out] key_count Returned number of keys counted (excluding FK).
4774 @param[out] key_parts Returned number of key segments (excluding FK).
4775 @param[out] fk_key_count Returned number of foreign keys.
4776 @param[in,out] redundant_keys Array where keys to be ignored will be marked.
4777 @param[in] se_index_flags Storage's flags for index support
4778 */
4779
4780 749475 static bool count_keys(const Mem_root_array<Key_spec *> &key_list,
4781 uint *key_count, uint *key_parts, uint *fk_key_count,
4782 Mem_root_array<bool> *redundant_keys,
4783 handler::Table_flags se_index_flags) {
4784 749475 *key_count = 0;
4785 749475 *key_parts = 0;
4786
4787
2/2
✓ Branch 0 taken 2691232 times.
✓ Branch 1 taken 749466 times.
3440699 for (size_t key_counter = 0; key_counter < key_list.size(); key_counter++) {
4788 2691232 const Key_spec *key = key_list[key_counter];
4789
4790 10533845 for (size_t key2_counter = 0;
4791
5/6
✓ Branch 0 taken 10533845 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8454306 times.
✓ Branch 3 taken 2079539 times.
✓ Branch 4 taken 8454306 times.
✓ Branch 5 taken 2079539 times.
10533845 key2_counter < key_list.size() && key_list[key2_counter] != key;
4792 key2_counter++) {
4793 8454306 const Key_spec *key2 = key_list[key2_counter];
4794 /*
4795 foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is
4796 'generated', and a generated key is a prefix of the other key.
4797 Then we do not need the generated shorter key.
4798
4799 KEYTYPE_SPATIAL and KEYTYPE_FULLTEXT cannot be used as
4800 supporting keys for foreign key constraints even if the
4801 generated key is prefix of such a key.
4802 */
4803
2/2
✓ Branch 0 taken 4232019 times.
✓ Branch 1 taken 3608779 times.
7840798 if ((key2->type != KEYTYPE_FOREIGN && key->type != KEYTYPE_FOREIGN &&
4804
4/4
✓ Branch 0 taken 4231881 times.
✓ Branch 1 taken 138 times.
✓ Branch 2 taken 4227141 times.
✓ Branch 3 taken 4740 times.
4232019 key2->type != KEYTYPE_SPATIAL && key2->type != KEYTYPE_FULLTEXT &&
4805
6/6
✓ Branch 0 taken 7840798 times.
✓ Branch 1 taken 613508 times.
✓ Branch 2 taken 4227121 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 611693 times.
✓ Branch 5 taken 7842613 times.
20522225 !redundant_keys->at(key2_counter) &&
4806
2/2
✓ Branch 0 taken 611693 times.
✓ Branch 1 taken 3615428 times.
4227121 !foreign_key_prefix(key, key2))) {
4807 /* TODO: issue warning message */
4808 /* mark that the generated key should be ignored */
4809
4/4
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 611655 times.
✓ Branch 2 taken 611655 times.
✓ Branch 3 taken 38 times.
611731 if (!key2->generated ||
4810
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
38 (key->generated && key->columns.size() < key2->columns.size()))
4811 611655 (*redundant_keys)[key_counter] = true;
4812 else {
4813 38 (*redundant_keys)[key2_counter] = true;
4814 38 (*key_parts) -= key2->columns.size();
4815 38 (*key_count)--;
4816 }
4817 611693 break;
4818 }
4819 }
4820
4821
2/2
✓ Branch 0 taken 2079577 times.
✓ Branch 1 taken 611655 times.
2691232 if (!redundant_keys->at(key_counter)) {
4822
2/2
✓ Branch 0 taken 612882 times.
✓ Branch 1 taken 1466695 times.
2079577 if (key->type == KEYTYPE_FOREIGN)
4823 612882 (*fk_key_count)++;
4824 else {
4825 1466695 uint mv_key_parts = 0;
4826 1466695 (*key_count)++;
4827 1466695 (*key_parts) += key->columns.size();
4828
2/2
✓ Branch 0 taken 2334559 times.
✓ Branch 1 taken 1466687 times.
3801246 for (uint i = 0; i < key->columns.size(); i++) {
4829 2334559 const Key_part_spec *kp = key->columns[i];
4830
6/6
✓ Branch 0 taken 911 times.
✓ Branch 1 taken 2333648 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 907 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 2334555 times.
2334559 if (!kp->is_ascending() && !(se_index_flags & HA_DESCENDING_INDEX)) {
4831 4 my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "descending indexes");
4832 4 return true;
4833 }
4834
6/6
✓ Branch 0 taken 860 times.
✓ Branch 1 taken 2333695 times.
✓ Branch 2 taken 423 times.
✓ Branch 3 taken 437 times.
✓ Branch 4 taken 423 times.
✓ Branch 5 taken 2334132 times.
2334555 if (kp->has_expression() && kp->get_expression()->returns_array()) {
4835
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 421 times.
423 if (mv_key_parts++) {
4836 2 my_error(ER_NOT_SUPPORTED_YET, MYF(0),
4837 "more than one multi-valued key part per index");
4838 2 return true;
4839 }
4840
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 420 times.
421 if (!(se_index_flags & HA_MULTI_VALUED_KEY_SUPPORT)) {
4841 1 my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0),
4842 "multi-valued indexes");
4843 1 return true;
4844 }
4845
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 419 times.
420 if (kp->is_explicit()) {
4846 1 my_error(ER_WRONG_USAGE, MYF(0), "multi-valued index",
4847 "explicit index order");
4848 1 return true;
4849 }
4850 }
4851 }
4852 }
4853 }
4854 }
4855 749466 return false;
4856 }
4857
4858 2332319 static bool prepare_key_column(THD *thd, HA_CREATE_INFO *create_info,
4859 List<Create_field> *create_list,
4860 const Key_spec *key, const Key_part_spec *column,
4861 const size_t column_nr, KEY *key_info,
4862 KEY_PART_INFO *key_part_info,
4863 const handler *file, int *auto_increment,
4864 const CHARSET_INFO **ft_key_charset) {
4865
1/2
✓ Branch 0 taken 2332320 times.
✗ Branch 1 not taken.
2332319 DBUG_TRACE;
4866
4867 /*
4868 Find the matching table column.
4869 */
4870 2332320 uint field = 0;
4871 2332320 Create_field *sql_field = nullptr;
4872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2332320 times.
2332320 assert(create_list);
4873
5/8
✓ Branch 0 taken 2332320 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2332320 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11422454 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11422445 times.
✓ Branch 7 taken 9 times.
11422455 for (Create_field &it : *create_list) {
4874
7/8
✓ Branch 0 taken 11417290 times.
✓ Branch 1 taken 5155 times.
✓ Branch 2 taken 11417290 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11417289 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2332311 times.
✓ Branch 7 taken 9090135 times.
22844890 if ((column->has_expression() || !is_hidden_by_system(&it)) &&
4875
3/4
✓ Branch 0 taken 11422445 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2332311 times.
✓ Branch 3 taken 9090134 times.
11422444 my_strcasecmp(system_charset_info, column->get_field_name(),
4876 it.field_name) == 0) {
4877 2332311 sql_field = &it;
4878 2332311 break;
4879 }
4880 9090135 field++;
4881 }
4882
4883
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2332311 times.
2332320 if (sql_field == nullptr) {
4884
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->get_field_name());
4885 9 return true;
4886 }
4887
4888 Functional_index_error_handler functional_index_error_handler(
4889
2/4
✓ Branch 0 taken 2332311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2332311 times.
✗ Branch 3 not taken.
4664622 sql_field, {key->name.str, key->name.length}, thd);
4890
4891 /*
4892 Virtual generated column checks.
4893 */
4894
2/2
✓ Branch 0 taken 5308 times.
✓ Branch 1 taken 2327002 times.
2332310 if (sql_field->is_virtual_gcol()) {
4895 5308 const char *errmsg = nullptr;
4896
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5305 times.
5308 if (key->type == KEYTYPE_FULLTEXT) {
4897 3 errmsg = "Fulltext index on virtual generated column";
4898 3 functional_index_error_handler.force_error_code(
4899 ER_FULLTEXT_FUNCTIONAL_INDEX);
4900
2/2
✓ Branch 0 taken 5302 times.
✓ Branch 1 taken 3 times.
5305 } else if (key->type == KEYTYPE_SPATIAL ||
4901
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5292 times.
5302 sql_field->sql_type == MYSQL_TYPE_GEOMETRY) {
4902 13 errmsg = "Spatial index on virtual generated column";
4903 13 functional_index_error_handler.force_error_code(
4904 ER_SPATIAL_FUNCTIONAL_INDEX);
4905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5292 times.
5292 } else if (key->type == KEYTYPE_PRIMARY) {
4906 errmsg = "Defining a virtual generated column as primary key";
4907 functional_index_error_handler.force_error_code(
4908 ER_FUNCTIONAL_INDEX_PRIMARY_KEY);
4909 }
4910
4911
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 5292 times.
5308 if (errmsg) {
4912
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 my_error(ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN, MYF(0), errmsg);
4913 16 return true;
4914 }
4915 /* Check if the storage engine supports indexes on virtual columns. */
4916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5292 times.
5292 if (!(file->ha_table_flags() & HA_CAN_INDEX_VIRTUAL_GENERATED_COLUMN)) {
4917 my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
4918 ha_resolve_storage_engine_name(file->ht),
4919 "Index on virtual generated column");
4920 return true;
4921 }
4922 5292 key_info->flags |= HA_VIRTUAL_GEN_KEY;
4923 }
4924
4925 // JSON columns cannot be used as keys.
4926
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 2332253 times.
2332294 if (sql_field->sql_type == MYSQL_TYPE_JSON) {
4927
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 my_error(ER_JSON_USED_AS_KEY, MYF(0), column->get_field_name());
4928 41 return true;
4929 }
4930
4931
2/2
✓ Branch 0 taken 246190 times.
✓ Branch 1 taken 2086063 times.
2332253 if (sql_field->auto_flags & Field::NEXT_NUMBER) {
4932
6/6
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 246079 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 85 times.
✓ Branch 4 taken 246105 times.
✓ Branch 5 taken 85 times.
246190 if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
4933 246105 (*auto_increment)--; // Field is used
4934 }
4935
4936 /*
4937 Check for duplicate columns.
4938 */
4939
1/2
✓ Branch 0 taken 3613667 times.
✗ Branch 1 not taken.
3613666 for (const Key_part_spec *dup_column : key->columns) {
4940
2/2
✓ Branch 0 taken 2332232 times.
✓ Branch 1 taken 1281435 times.
3613667 if (dup_column == column) break;
4941
3/4
✓ Branch 0 taken 1281435 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 1281413 times.
1281435 if (!my_strcasecmp(system_charset_info, column->get_field_name(),
4942 dup_column->get_field_name())) {
4943
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 my_error(ER_DUP_FIELDNAME, MYF(0), column->get_field_name());
4944 22 return true;
4945 }
4946 }
4947
4948 /* compressed column is not allowed to be defined as a key part */
4949
2/4
✓ Branch 0 taken 2332231 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2332231 times.
2332232 DBUG_EXECUTE_IF("remove_compressed_attributes_for_keys",
4950 sql_field->set_column_format(COLUMN_FORMAT_TYPE_DEFAULT););
4951
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2332231 times.
2332231 if (sql_field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED) {
4952
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
1 my_error(ER_COMPRESSED_COLUMN_USED_AS_KEY, MYF(0),
4953 column->get_field_name());
4954 return true;
4955 }
4956
4957 uint column_length;
4958
2/2
✓ Branch 0 taken 2922 times.
✓ Branch 1 taken 2329309 times.
2332231 if (key->type == KEYTYPE_FULLTEXT) {
4959 8174 if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
4960
2/2
✓ Branch 0 taken 1045 times.
✓ Branch 1 taken 1285 times.
2330 sql_field->sql_type != MYSQL_TYPE_VARCHAR &&
4961
2/2
✓ Branch 0 taken 1037 times.
✓ Branch 1 taken 8 times.
1045 !is_blob(sql_field->sql_type)) ||
4962
1/2
✓ Branch 0 taken 2914 times.
✗ Branch 1 not taken.
2914 sql_field->charset == &my_charset_bin ||
4963
6/6
✓ Branch 0 taken 2330 times.
✓ Branch 1 taken 592 times.
✓ Branch 2 taken 2912 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 2910 times.
8756 sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
4964
4/4
✓ Branch 0 taken 485 times.
✓ Branch 1 taken 2427 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 483 times.
2912 (*ft_key_charset && sql_field->charset != *ft_key_charset)) {
4965
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 my_error(ER_BAD_FT_COLUMN, MYF(0), column->get_field_name());
4966 12 return true;
4967 }
4968 2910 *ft_key_charset = sql_field->charset;
4969 /*
4970 for fulltext keys keyseg length is 1 for blobs (it's ignored in ft
4971 code anyway, and 0 (set to column width later) for char's. it has
4972 to be correct col width for char's, as char data are not prefixed
4973 with length (unlike blobs, where ft code takes data length from a
4974 data prefix, ignoring column->length).
4975 */
4976 2910 column_length = is_blob(sql_field->sql_type);
4977 } else {
4978
3/3
✓ Branch 0 taken 1378 times.
✓ Branch 1 taken 980725 times.
✓ Branch 2 taken 1347206 times.
2329309 switch (sql_field->sql_type) {
4979 1378 case MYSQL_TYPE_GEOMETRY:
4980 /* All indexes on geometry columns are R-tree indexes. */
4981
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1366 times.
1378 if (key->columns.size() > 1) {
4982
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 my_error(ER_TOO_MANY_KEY_PARTS, MYF(0), 1);
4983 12 return true;
4984 }
4985 1366 key_info->flags |= HA_SPATIAL;
4986
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1350 times.
1366 if (key->key_create_info.is_algorithm_explicit &&
4987
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 key_info->algorithm != HA_KEY_ALG_RTREE) {
4988
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
13 assert(key->key_create_info.algorithm == HA_KEY_ALG_HASH ||
4989 key->key_create_info.algorithm == HA_KEY_ALG_BTREE);
4990
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 my_error(ER_INDEX_TYPE_NOT_SUPPORTED_FOR_SPATIAL_INDEX, MYF(0),
4991
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 7 times.
13 key->key_create_info.algorithm == HA_KEY_ALG_HASH ? "HASH"
4992 : "BTREE");
4993 13 return true;
4994 }
4995 1353 key_info->algorithm = HA_KEY_ALG_RTREE;
4996 [[fallthrough]];
4997 982078 case MYSQL_TYPE_TINY_BLOB:
4998 case MYSQL_TYPE_MEDIUM_BLOB:
4999 case MYSQL_TYPE_LONG_BLOB:
5000 case MYSQL_TYPE_BLOB:
5001 case MYSQL_TYPE_JSON:
5002 case MYSQL_TYPE_VAR_STRING:
5003 case MYSQL_TYPE_STRING:
5004 case MYSQL_TYPE_VARCHAR:
5005 case MYSQL_TYPE_ENUM:
5006 case MYSQL_TYPE_SET:
5007 982078 column_length =
5008 982078 column->get_prefix_length() * sql_field->charset->mbmaxlen;
5009 982078 break;
5010 1347206 default:
5011 1347206 column_length = column->get_prefix_length();
5012 }
5013
5014
2/2
✓ Branch 0 taken 2327978 times.
✓ Branch 1 taken 1306 times.
2329284 if (key->type == KEYTYPE_SPATIAL ||
5015
2/2
✓ Branch 0 taken 2327919 times.
✓ Branch 1 taken 59 times.
2327978 key_info->algorithm == HA_KEY_ALG_RTREE ||
5016
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2327918 times.
2327919 sql_field->sql_type == MYSQL_TYPE_GEOMETRY) {
5017
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1353 times.
1366 if (column_length) {
5018
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 my_error(ER_WRONG_SUB_KEY, MYF(0));
5019 13 return true;
5020 }
5021
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1340 times.
1353 if (sql_field->sql_type != MYSQL_TYPE_GEOMETRY) {
5022
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 my_error(ER_SPATIAL_MUST_HAVE_GEOM_COL, MYF(0));
5023 13 return true;
5024 }
5025
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1325 times.
1340 if (key_info->flags & HA_NOSAME) {
5026
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 my_error(ER_SPATIAL_UNIQUE_INDEX, MYF(0));
5027 15 return true;
5028 }
5029
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1313 times.
1325 if (column->is_explicit()) {
5030
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 my_error(ER_WRONG_USAGE, MYF(0), "spatial/fulltext/hash index",
5031 "explicit index order");
5032 12 return true;
5033 }
5034
5035 /*
5036 If the field is without an SRID specification, issue a warning telling
5037 the user that this index will not be used by the optimizer (useless
5038 spatial index). We do however have to allow creating such index in
5039 order to support dump/restore from older MySQL versions to new
5040 versions.
5041
5042 NOTE: At this stage of ALTER TABLE/CREATE INDEX/whatever DDL, we may
5043 have copied all existing indexes into key list. Thus, this function may
5044 run for indexes that already exists. The variable
5045 "check_for_duplicate_indexes" will however be set to "false" for indexes
5046 that already are created, so we use this variable to distinguish between
5047 indexes that are to be created, and those that already are created.
5048 */
5049
6/6
✓ Branch 0 taken 1192 times.
✓ Branch 1 taken 121 times.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 1158 times.
✓ Branch 4 taken 34 times.
✓ Branch 5 taken 1279 times.
1313 if (key->check_for_duplicate_indexes && !sql_field->m_srid.has_value()) {
5050
2/4
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
34 push_warning_printf(
5051 thd, Sql_condition::SL_WARNING, WARN_USELESS_SPATIAL_INDEX,
5052 ER_THD(thd, WARN_USELESS_SPATIAL_INDEX), sql_field->field_name);
5053 }
5054
5055 /*
5056 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
5057 Lately we'll extend this code to support more dimensions
5058 */
5059 1313 column_length = 4 * sizeof(double);
5060 }
5061
5062
2/2
✓ Branch 0 taken 9195 times.
✓ Branch 1 taken 2320037 times.
2329231 if (is_blob(sql_field->sql_type)) {
5063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9195 times.
9195 if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS)) {
5064 my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->get_field_name());
5065 return true;
5066 }
5067
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9191 times.
9195 if (!column_length) {
5068
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->get_field_name());
5069 4 return true;
5070 }
5071 }
5072
5073
2/2
✓ Branch 0 taken 780918 times.
✓ Branch 1 taken 1548310 times.
2329228 if (key->type == KEYTYPE_PRIMARY) {
5074 /*
5075 Set NO_DEFAULT_VALUE_FLAG for the PRIMARY KEY column if default
5076 values is not explicitly provided for the column in CREATE TABLE
5077 statement and it is not an AUTO_INCREMENT field.
5078
5079 Default values for TIMESTAMP/DATETIME needs special handling as:
5080
5081 a) If default is explicitly specified (lets say this as case 1) :
5082 DEFAULT CURRENT_TIMESTAMP
5083 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
5084 MySQL does not set sql_field->def flag , but sets
5085 Field::DEFAULT_NOW in Create_info::auto_flags.
5086 This flags are also set during timestamp column promotion (case2)
5087
5088 When explicit_defaults_for_timestamp is not set, the behavior
5089 expected in both case1 and case2 is to retain the defaults even
5090 when the column participates in PRIMARY KEY. When
5091 explicit_defaults_for_timestamp is set, the promotion logic
5092 is disabled and the above mentioned flag is not used implicitly.
5093
5094 b) If explicit_defaults_for_timestamp variable is not set:
5095 Default value assigned due to first timestamp column promotion is
5096 retained.
5097 Default constant value assigned due to implicit promotion of second
5098 timestamp column is removed.
5099 */
5100 2268762 if (!sql_field->constant_default &&
5101
2/2
✓ Branch 0 taken 469225 times.
✓ Branch 1 taken 237701 times.
706926 !(sql_field->flags & AUTO_INCREMENT_FLAG) &&
5102
2/2
✓ Branch 0 taken 1546 times.
✓ Branch 1 taken 467679 times.
469225 !(real_type_with_now_as_default(sql_field->sql_type) &&
5103
6/6
✓ Branch 0 taken 706926 times.
✓ Branch 1 taken 73992 times.
✓ Branch 2 taken 799 times.
✓ Branch 3 taken 747 times.
✓ Branch 4 taken 468463 times.
✓ Branch 5 taken 312455 times.
1488643 (sql_field->auto_flags & Field::DEFAULT_NOW)) &&
5104
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 468464 times.
468478 !(sql_field->m_default_val_expr &&
5105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 (sql_field->auto_flags & Field::GENERATED_FROM_EXPRESSION))) {
5106 468463 sql_field->flags |= NO_DEFAULT_VALUE_FLAG;
5107 }
5108 /*
5109 Emitting error when field is a part of primary key and is
5110 explicitly requested to be NULL by the user.
5111 */
5112
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 780916 times.
780918 if ((sql_field->flags & EXPLICIT_NULL_FLAG)) {
5113
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_PRIMARY_CANT_HAVE_NULL, MYF(0));
5114 2 return true;
5115 }
5116 }
5117
5118
2/2
✓ Branch 0 taken 321063 times.
✓ Branch 1 taken 2008163 times.
2329226 if (!(sql_field->flags & NOT_NULL_FLAG)) {
5119
2/2
✓ Branch 0 taken 10973 times.
✓ Branch 1 taken 310090 times.
321063 if (key->type == KEYTYPE_PRIMARY) {
5120 /* Implicitly set primary key fields to NOT NULL for ISO conf. */
5121 10973 sql_field->flags |= NOT_NULL_FLAG;
5122 10973 sql_field->is_nullable = false;
5123 10973 create_info->null_bits--;
5124 } else {
5125 310090 key_info->flags |= HA_NULL_PART_KEY;
5126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 310090 times.
310090 if (!(file->ha_table_flags() & HA_NULL_IN_KEY)) {
5127 my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->get_field_name());
5128 return true;
5129 }
5130
2/2
✓ Branch 0 taken 310085 times.
✓ Branch 1 taken 5 times.
310090 if (key->type == KEYTYPE_SPATIAL ||
5131
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 310081 times.
310085 sql_field->sql_type == MYSQL_TYPE_GEOMETRY) {
5132
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_error(ER_SPATIAL_CANT_HAVE_NULL, MYF(0));
5133 9 return true;
5134 }
5135 }
5136 }
5137 } // key->type != KEYTYPE_FULLTEXT
5138
5139 2332127 key_part_info->fieldnr = field;
5140 2332127 key_part_info->offset = static_cast<uint16>(sql_field->offset);
5141
2/2
✓ Branch 0 taken 2331225 times.
✓ Branch 1 taken 901 times.
2332127 key_part_info->key_part_flag |= column->is_ascending() ? 0 : HA_REVERSE_SORT;
5142
5143
1/2
✓ Branch 0 taken 2332127 times.
✗ Branch 1 not taken.
2332126 size_t key_part_length = sql_field->key_length();
5144
5145
2/2
✓ Branch 0 taken 13601 times.
✓ Branch 1 taken 2318526 times.
2332127 if (column_length) {
5146
2/2
✓ Branch 0 taken 10228 times.
✓ Branch 1 taken 3373 times.
13601 if (is_blob(sql_field->sql_type)) {
5147 10228 key_part_length = column_length;
5148 /*
5149 There is a possibility that the given prefix length is less
5150 than the engine max key part length, but still greater
5151 than the BLOB field max size. We handle this case
5152 using the max_field_size variable below.
5153 */
5154 10228 size_t max_field_size = blob_length_by_type(sql_field->sql_type);
5155 30670 if (key_part_length > max_field_size ||
5156
7/8
✓ Branch 0 taken 10214 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 10214 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10165 times.
✓ Branch 5 taken 49 times.
✓ Branch 6 taken 90 times.
✓ Branch 7 taken 10138 times.
20393 key_part_length > file->max_key_length() ||
5157
3/4
✓ Branch 0 taken 10165 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 10138 times.
10165 key_part_length > file->max_key_part_length(create_info)) {
5158 // Given prefix length is too large, adjust it.
5159 90 key_part_length =
5160
2/4
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
90 min(file->max_key_length(), file->max_key_part_length(create_info));
5161
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 if (max_field_size)
5162 90 key_part_length = min(key_part_length, max_field_size);
5163
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 15 times.
90 if (key->type & KEYTYPE_MULTIPLE) {
5164 /* not a critical problem */
5165
2/4
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 75 times.
✗ Branch 3 not taken.
75 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_TOO_LONG_KEY,
5166 ER_THD(thd, ER_TOO_LONG_KEY),
5167 static_cast<int>(key_part_length));
5168 /* Align key length to multibyte char boundary */
5169 75 key_part_length -= key_part_length % sql_field->charset->mbmaxlen;
5170 /*
5171 If SQL_MODE is STRICT, then report error, else report warning
5172 and continue execution.
5173 */
5174
3/4
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
✓ Branch 3 taken 32 times.
90 if (thd->is_error()) return true;
5175 } else {
5176
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
5177
2/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
15 if (thd->is_error()) return true;
5178 }
5179 }
5180 } // is_blob
5181 // Catch invalid use of partial keys
5182 8815 else if (sql_field->sql_type != MYSQL_TYPE_GEOMETRY &&
5183 // is the key partial?
5184
6/6
✓ Branch 0 taken 2069 times.
✓ Branch 1 taken 1304 times.
✓ Branch 2 taken 1768 times.
✓ Branch 3 taken 301 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 3363 times.
5141 column_length != key_part_length &&
5185 // is prefix length bigger than field length?
5186
2/2
✓ Branch 0 taken 1759 times.
✓ Branch 1 taken 9 times.
1768 (column_length > key_part_length ||
5187 // can the field have a partial key?
5188
3/4
✓ Branch 0 taken 1759 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1758 times.
✓ Branch 3 taken 1 times.
1759 !Field::type_can_have_key_part(sql_field->sql_type) ||
5189 // does the storage engine allow prefixed search?
5190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1758 times.
1758 ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
5191 // and is this a 'unique' key?
5192 (key_info->flags & HA_NOSAME)))) {
5193
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 my_error(ER_WRONG_SUB_KEY, MYF(0));
5194 10 return true;
5195
1/2
✓ Branch 0 taken 3363 times.
✗ Branch 1 not taken.
3363 } else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
5196 3363 key_part_length = column_length;
5197 } // column_length
5198
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2318523 times.
2318526 else if (key_part_length == 0) {
5199
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
3 if (is_field_for_functional_index(sql_field)) {
5200 // In case this is a functional index, print a more friendly error
5201 // message.
5202
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 Item *expression = column->get_expression();
5203 2 auto flags =
5204 enum_query_type(QT_NO_DB | QT_NO_TABLE | QT_FORCE_INTRODUCERS);
5205 2 String out;
5206
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 expression->print(thd, &out, flags);
5207
5208 // Append a NULL-terminator, since Item::print does not necessarily add
5209 // one.
5210
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 out.append('\0');
5211
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_WRONG_KEY_COLUMN_FUNCTIONAL_INDEX, MYF(0), out.ptr());
5212 2 } else {
5213
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->get_field_name());
5214 }
5215 3 return true;
5216 }
5217
5218
5/6
✓ Branch 0 taken 2332055 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
✓ Branch 3 taken 2331976 times.
✓ Branch 4 taken 48 times.
✓ Branch 5 taken 2332007 times.
2332135 if (key_part_length > file->max_key_part_length(create_info) &&
5219
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 31 times.
79 key->type != KEYTYPE_FULLTEXT) {
5220
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 key_part_length = file->max_key_part_length(create_info);
5221
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 14 times.
48 if (key->type & KEYTYPE_MULTIPLE) {
5222 /* not a critical problem */
5223
2/4
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
34 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_TOO_LONG_KEY,
5224 ER_THD(thd, ER_TOO_LONG_KEY),
5225 static_cast<int>(key_part_length));
5226 /* Align key length to multibyte char boundary */
5227 34 key_part_length -= key_part_length % sql_field->charset->mbmaxlen;
5228 /*
5229 If SQL_MODE is STRICT, then report error, else report warning
5230 and continue execution.
5231 */
5232
3/4
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 21 times.
34 if (thd->is_error()) return true;
5233
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 } else if ((thd->lex->alter_info->flags & Alter_info::ALTER_OPTIONS) &&
5234
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
13 (create_info->used_fields & HA_CREATE_USED_CHARSET)) {
5235 1 my_error(ER_COLUMN_CHANGE_SIZE, MYF(0), sql_field->field_name,
5236
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 sql_field->field->table->s->table_name.str, key->name.str,
5237 key_part_length);
5238 1 return true;
5239 } else {
5240
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
5241
3/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 1 times.
13 if (thd->is_error()) return true;
5242 }
5243 }
5244 2332029 key_part_info->length = static_cast<uint16>(key_part_length);
5245
5246 /*
5247 Use packed keys for long strings on the first column
5248
5249 Due to incorrect usage of sql_field->pack_flag & FIELDFLAG_BLOB check
5250 we have used packing for some columns which are not strings or BLOBs
5251 (see also is_phony_blob()). Since changing this would mean breaking
5252 binary compatibility for MyISAM tables with indexes on such columns
5253 we mimic this buggy behavior here.
5254 */
5255 4695853 if ((create_info->db_type->flags & HTON_SUPPORTS_PACKED_KEYS) &&
5256
6/6
✓ Branch 0 taken 31795 times.
✓ Branch 1 taken 2300234 times.
✓ Branch 2 taken 31792 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 13692 times.
✓ Branch 5 taken 2318337 times.
2363821 !((create_info->table_options & HA_OPTION_NO_PACK_KEYS)) &&
5257
2/2
✓ Branch 0 taken 23562 times.
✓ Branch 1 taken 8230 times.
31792 (key_part_length >= KEY_DEFAULT_PACK_LENGTH &&
5258
2/2
✓ Branch 0 taken 10642 times.
✓ Branch 1 taken 12920 times.
23562 (sql_field->sql_type == MYSQL_TYPE_STRING ||
5259
4/4
✓ Branch 0 taken 10185 times.
✓ Branch 1 taken 457 times.
✓ Branch 2 taken 9877 times.
✓ Branch 3 taken 308 times.
20827 sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
5260
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 9870 times.
20062 is_blob(sql_field->sql_type) ||
5261 9877 is_phony_blob(sql_field->sql_type, sql_field->decimals)))) {
5262
2/2
✓ Branch 0 taken 6359 times.
✓ Branch 1 taken 285 times.
6644 if ((column_nr == 0 &&
5263
2/2
✓ Branch 0 taken 6352 times.
✓ Branch 1 taken 7 times.
13003 (is_blob(sql_field->sql_type) ||
5264
4/4
✓ Branch 0 taken 6644 times.
✓ Branch 1 taken 7048 times.
✓ Branch 2 taken 749 times.
✓ Branch 3 taken 12943 times.
33743 is_phony_blob(sql_field->sql_type, sql_field->decimals))) ||
5265
2/2
✓ Branch 0 taken 457 times.
✓ Branch 1 taken 12943 times.
13400 sql_field->sql_type == MYSQL_TYPE_VARCHAR)
5266 749 key_info->flags |= HA_BINARY_PACK_KEY;
5267 else
5268 12943 key_info->flags |= HA_PACK_KEY;
5269 }
5270
5271 /*
5272 Check if the key segment is partial, set the key flag
5273 accordingly. Note that fulltext indexes ignores prefixes.
5274 */
5275
4/4
✓ Branch 0 taken 2329119 times.
✓ Branch 1 taken 2910 times.
✓ Branch 2 taken 11911 times.
✓ Branch 3 taken 2320119 times.
4661149 if (key->type != KEYTYPE_FULLTEXT &&
5276
3/4
✓ Branch 0 taken 2329120 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11911 times.
✓ Branch 3 taken 2317209 times.
2329119 key_part_length != sql_field->key_length()) {
5277 11911 key_info->flags |= HA_KEY_HAS_PART_KEY_SEG;
5278 11911 key_part_info->key_part_flag |= HA_PART_KEY_SEG;
5279 }
5280
5281 2332030 key_info->key_length += key_part_length;
5282 2332030 return false;
5283 2332320 }
5284
5285 /**
5286 Check if candidate parent/supporting key contains exactly the same
5287 columns as the foreign key, possibly, in different order. Also check
5288 that columns usage by key is acceptable, i.e. key is not over column
5289 prefix.
5290
5291 @tparam F Function class which returns foreign key's
5292 referenced or referencing (depending on whether
5293 we check candidate parent or supporting key)
5294 column name by its index.
5295 @param alter_info Alter_info describing columns in parent or
5296 child table.
5297 @param fk_col_count Number of columns in the foreign key.
5298 @param fk_columns Object of F type bound to the specific foreign key
5299 for which parent/supporting key check is carried
5300 out.
5301 @param key KEY object describing candidate parent/supporting
5302 key.
5303
5304 @sa fk_is_key_exact_match_any_order(uint, F, dd::Index).
5305
5306 @retval True - Key is proper parent/supporting key for the foreign key.
5307 @retval False - Key can't be parent/supporting key for the foreign key.
5308 */
5309 template <class F>
5310 static bool fk_is_key_exact_match_any_order(Alter_info *alter_info,
5311 uint fk_col_count,
5312 const F &fk_columns,
5313 const KEY *key) {
5314 if (fk_col_count != key->user_defined_key_parts) return false;
5315
5316 for (uint i = 0; i < key->user_defined_key_parts; i++) {
5317 // Prefix parts are considered non-matching.
5318 if (key->key_part[i].key_part_flag & HA_PART_KEY_SEG) return false;
5319
5320 const Create_field *col =
5321 get_field_by_index(alter_info, key->key_part[i].fieldnr);
5322
5323 uint j = 0;
5324 while (j < fk_col_count) {
5325 if (my_strcasecmp(system_charset_info, col->field_name, fk_columns(j)) ==
5326 0)
5327 break;
5328 j++;
5329 }
5330 if (j == fk_col_count) return false;
5331
5332 /*
5333 Foreign keys over virtual columns are not allowed.
5334 This is checked at earlier stage.
5335 */
5336 assert(!col->is_virtual_gcol());
5337 }
5338
5339 return true;
5340 }
5341
5342 /**
5343 Count how many elements from the start of the candidate parent/supporting
5344 key match elements at the start of the foreign key (prefix parts are
5345 considered non-matching).
5346
5347 @tparam F Function class which returns foreign key's
5348 referenced or referencing (depending on whether
5349 we check candidate parent or supporting key)
5350 column name by its index.
5351 @param alter_info Alter_info describing columns in parent or
5352 child table.
5353 @param fk_col_count Number of columns in the foreign key.
5354 @param fk_columns Object of F type bound to the specific foreign key
5355 for which parent/supporting key check is carried
5356 out.
5357 @param key KEY object describing candidate parent/supporting
5358 key.
5359 @param hidden_cols_key If non-nullptr, points to KEY object representing
5360 primary key for the table, which columns are added
5361 to the candidate parent key and should be taken
5362 into account when considering this parent key.
5363
5364 @sa fk_key_prefix_match_count(uint, F, dd::Index, bool).
5365
5366 @retval Number of matching columns.
5367 */
5368 template <class F>
5369 3914148 static uint fk_key_prefix_match_count(Alter_info *alter_info, uint fk_col_count,
5370 const F &fk_columns, const KEY *key,
5371 const KEY *hidden_cols_key) {
5372 3914148 uint col_idx = 0;
5373
5374
2/2
✓ Branch 0 taken 2245169 times.
✓ Branch 1 taken 337447 times.
5165232 for (; col_idx < key->user_defined_key_parts; ++col_idx) {
5375
2/2
✓ Branch 0 taken 287603 times.
✓ Branch 1 taken 1957566 times.
4490338 if (col_idx == fk_col_count) break;
5376 // Prefix parts are considered non-matching.
5377
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1957560 times.
3915132 if (key->key_part[col_idx].key_part_flag & HA_PART_KEY_SEG) break;
5378 const Create_field *col =
5379 3915120 get_field_by_index(alter_info, key->key_part[col_idx].fieldnr);
5380
5381 3915120 if (my_strcasecmp(system_charset_info, col->field_name,
5382
2/2
✓ Branch 0 taken 1332018 times.
✓ Branch 1 taken 625542 times.
3915120 fk_columns(col_idx)) != 0)
5383 2664036 break;
5384
5385 /*
5386 Foreign keys over virtual columns are not allowed.
5387 This is checked at earlier stage.
5388 */
5389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 625542 times.
1251084 assert(!col->is_virtual_gcol());
5390 }
5391
5392
3/6
✓ Branch 0 taken 1332024 times.
✓ Branch 1 taken 625050 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1332024 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
3914148 if (col_idx < fk_col_count && col_idx == key->user_defined_key_parts &&
5393 hidden_cols_key) {
5394 /*
5395 We have not found all foreign key columns and have not encountered
5396 unsuitable columns so far. Continue counting columns from hidden
5397 part of the key if it exists.
5398 */
5399 for (uint add_col_idx = 0;
5400 add_col_idx < hidden_cols_key->user_defined_key_parts; ++add_col_idx) {
5401 if (col_idx == fk_col_count) break;
5402
5403 KEY_PART_INFO *add_key_part = hidden_cols_key->key_part + add_col_idx;
5404 /*
5405 Hidden part of the key doesn't include columns already in the key,
5406 unless they are used as prefix columns (which is impossible here).
5407 */
5408 if (std::any_of(key->key_part,
5409 key->key_part + key->user_defined_key_parts,
5410 [add_key_part](const KEY_PART_INFO &key_part) {
5411 return key_part.fieldnr == add_key_part->fieldnr;
5412 }))
5413 continue;
5414 /*
5415 prepare_self_ref_fk_parent_key() ensures that we can't meet
5416 primary keys with prefix parts here.
5417 */
5418 assert(!(add_key_part->key_part_flag & HA_PART_KEY_SEG));
5419
5420 const Create_field *col =
5421 get_field_by_index(alter_info, add_key_part->fieldnr);
5422
5423 if (my_strcasecmp(system_charset_info, col->field_name,
5424 fk_columns(col_idx)) != 0)
5425 break;
5426
5427 assert(!col->is_virtual_gcol());
5428 ++col_idx;
5429 }
5430 }
5431
5432 3914148 return col_idx;
5433 }
5434
5435 /**
5436 Check if candidate parent/supporting key contains all columns from the
5437 foreign key at its start and in the same order it is in the foreign key.
5438 Also check that columns usage by key is acceptable, i.e. key is not over
5439 column prefix.
5440
5441 @tparam F Function class which returns foreign key's
5442 referenced or referencing (depending on whether
5443 we check candidate parent or supporting key)
5444 column name by its index.
5445 @param alter_info Alter_info describing columns in parent or
5446 child table.
5447 @param fk_col_count Number of columns in the foreign key.
5448 @param fk_columns Object of F type bound to the specific foreign key
5449 for which parent/supporting key check is carried
5450 out.
5451 @param key KEY object describing candidate parent/supporting
5452 key.
5453 @param hidden_cols_key If non-nullptr, points to KEY object representing
5454 primary key for the table, which columns are added
5455 to the candidate parent key and should be taken
5456 into account when considering this parent key.
5457
5458 @sa fk_key_is_full_prefix_match(uint, F, dd::Index, bool).
5459
5460 @retval True - Key is proper parent/supporting key for the foreign key.
5461 @retval False - Key can't be parent/supporting key for the foreign key.
5462 */
5463 template <class F>
5464 3914324 static bool fk_key_is_full_prefix_match(Alter_info *alter_info,
5465 uint fk_col_count, const F &fk_columns,
5466 const KEY *key,
5467 const KEY *hidden_cols_key) {
5468 /*
5469 The index may have more elements, but must start with the same
5470 elements as the FK.
5471 */
5472 3914324 if (fk_col_count >
5473
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 1957074 times.
3914324 key->user_defined_key_parts +
5474
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1957162 times.
3914324 (hidden_cols_key ? hidden_cols_key->user_defined_key_parts : 0))
5475 176 return false;
5476
5477 3914148 uint match_count = fk_key_prefix_match_count(
5478 alter_info, fk_col_count, fk_columns, key, hidden_cols_key);
5479 3914148 return (match_count == fk_col_count);
5480 }
5481
5482 /**
5483 Check if parent key for self-referencing foreign key exists, set
5484 foreign key's unique constraint name accordingly. Emit error if
5485 no parent key found.
5486
5487 @note Prefer unique key if possible. If parent key is non-unique
5488 unique constraint name is set to NULL.
5489
5490 @note Explicitly skip the supporting index as a candidate parent
5491 index to maintain previous behavior for engines that require
5492 the two indexes to be different.
5493
5494 @param hton Handlerton for table's storage engine.
5495 @param alter_info Alter_info object describing parent table.
5496 @param key_info_buffer Array describing keys in parent table.
5497 @param key_count Number of keys in parent table.
5498 @param supporting_key Pointer to KEY representing the supporting
5499 index.
5500 @param old_fk_table dd::Table object from which pre-existing
5501 FK comes from. nullptr if this FK is newly
5502 added.
5503 @param[in,out] fk FOREIGN_KEY object describing the FK, its
5504 unique_index_name member will be updated
5505 if matching unique constraint is found.
5506
5507 @retval Operation result. False if success.
5508 */
5509 12012 static bool prepare_self_ref_fk_parent_key(
5510 handlerton *hton, Alter_info *alter_info, const KEY *key_info_buffer,
5511 const uint key_count, const KEY *supporting_key,
5512 const dd::Table *old_fk_table, FOREIGN_KEY *fk) {
5513 12012 auto fk_columns_lambda = [fk](uint i) { return fk->fk_key_part[i].str; };
5514
2/2
✓ Branch 0 taken 12013 times.
✓ Branch 1 taken 1 times.
12014 for (const KEY *key = key_info_buffer; key < key_info_buffer + key_count;
5515 key++) {
5516 // We can't use FULLTEXT or SPATIAL indexes.
5517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12013 times.
12013 if (key->flags & (HA_FULLTEXT | HA_SPATIAL)) continue;
5518
5519
1/2
✓ Branch 0 taken 12013 times.
✗ Branch 1 not taken.
12013 if (hton->foreign_keys_flags &
5520 HTON_FKS_NEED_DIFFERENT_PARENT_AND_SUPPORTING_KEYS) {
5521 /*
5522 The storage engine does not support using the same index for both the
5523 supporting index and the parent index. In this case, the supporting
5524 index cannot be a candidate parent index, and must be skipped.
5525 */
5526
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12012 times.
12013 if (key == supporting_key) continue;
5527 }
5528
5529
1/2
✓ Branch 0 taken 12012 times.
✗ Branch 1 not taken.
12012 if (hton->foreign_keys_flags & HTON_FKS_WITH_PREFIX_PARENT_KEYS) {
5530 /*
5531 Engine supports unique and non unique-parent keys which contain full
5532 foreign key as its prefix. Example: InnoDB.
5533
5534 Primary and unique keys are sorted before non-unique keys.
5535 So if there is suitable unique parent key we will always find
5536 it before encountering any non-unique keys.
5537 */
5538
5539 12012 const KEY *hidden_cols_key = nullptr;
5540
5541
1/2
✓ Branch 0 taken 12012 times.
✗ Branch 1 not taken.
12012 if (hton->foreign_keys_flags & HTON_FKS_WITH_EXTENDED_PARENT_KEYS) {
5542 /*
5543 Engine considers hidden part of key (columns from primary key
5544 which are implicitly added to secondary keys) when determines
5545 if it can serve as parent. Example: InnoDB.
5546
5547 Since KEY objects do not contain information about hidden parts
5548 of the keys at this point, we have to figure out list of hidden
5549 columns based on KEY object for explicit or implicit primary key.
5550 For the sake of consistency with non-self-referencing case we
5551 exclude primary keys with prefix elements from our consideration.
5552
5553 Thanks to the way keys are sorted, to find primary key it is
5554 enough to check if the first key in key array satisfies
5555 requirements on candidate key (unique, without null, prefix or
5556 virtual parts). This also automatically excludes explicit primary
5557 keys with prefix parts.
5558 */
5559
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12012 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12012 if (key != key_info_buffer && (key_info_buffer->flags & HA_NOSAME) &&
5560 !(key_info_buffer->flags &
5561 (HA_NULL_PART_KEY | HA_KEY_HAS_PART_KEY_SEG |
5562 HA_VIRTUAL_GEN_KEY)))
5563 hidden_cols_key = key_info_buffer;
5564 }
5565
5566
3/4
✓ Branch 0 taken 12012 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12011 times.
✓ Branch 3 taken 1 times.
12012 if (fk_key_is_full_prefix_match(alter_info, fk->key_parts,
5567 fk_columns_lambda, key,
5568 hidden_cols_key)) {
5569 /*
5570 We only store names of PK or UNIQUE keys in UNIQUE_CONSTRAINT_NAME.
5571 InnoDB allows non-unique indexes as parent keys for which NULL is
5572 stored.
5573 */
5574
2/2
✓ Branch 0 taken 12009 times.
✓ Branch 1 taken 2 times.
12011 if (key->flags & HA_NOSAME)
5575 12009 fk->unique_index_name = key->name;
5576 else
5577 2 fk->unique_index_name = nullptr;
5578 12011 return false;
5579 }
5580 } else {
5581 /*
5582 Default case. Engine only supports unique parent keys which
5583 contain exactly the same columns as foreign key, possibly
5584 in different order. Example: NDB.
5585 */
5586 if ((key->flags & HA_NOSAME) &&
5587 fk_is_key_exact_match_any_order(alter_info, fk->key_parts,
5588 fk_columns_lambda, key)) {
5589 fk->unique_index_name = key->name;
5590 return false;
5591 }
5592 }
5593 }
5594
5595 // No matching parent key!
5596
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (old_fk_table == nullptr) {
5597 // This is new foreign key for which parent key is missing.
5598
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_FK_NO_INDEX_PARENT, MYF(0), fk->name, fk->ref_table.str);
5599 } else {
5600 /*
5601 Old foreign key for which parent key or supporting key must have
5602 been dropped by this ALTER TABLE. Some analysis is needed to determine
5603 what has been dropped.
5604
5605 Find old foreign key definition first.
5606 */
5607 auto same_name = [fk](const dd::Foreign_key *el) {
5608 return my_strcasecmp(system_charset_info, fk->name, el->name().c_str()) ==
5609 0;
5610 };
5611
5612 auto old_fk = std::find_if(old_fk_table->foreign_keys().begin(),
5613 old_fk_table->foreign_keys().end(), same_name);
5614 assert(old_fk != old_fk_table->foreign_keys().end());
5615
5616 /*
5617 Then, unless the SE supports it, we need to find the old
5618 supporting key, to avoid selecting the incorrect parent key, and to
5619 make sure we determine whether the supporting or the parent key was
5620 dropped. This is done as follows:
5621
5622 - If the name of the old and new supporting key is the same,
5623 then we have either dropped the parent key, or we have dropped
5624 the supporting key and renamed another key to the supporting
5625 key's name.
5626 - If the name of the old and new supporting key is different,
5627 then we have either dropped the supporting key, or we have dropped
5628 the parent key and renamed the supporting key to a different name.
5629
5630 When finding the original key name, just getting the unique constraint
5631 name won't work for non-unique parent keys. Ideally, we should be
5632 using the handlerton of the old table version below, however, in
5633 practice, the new table version's handlerton works just fine, since
5634 we do not allow changing storage engines for tables with foreign keys.
5635 */
5636 const char *dropped_key = "<unknown key name>";
5637 if (hton->foreign_keys_flags &
5638 HTON_FKS_NEED_DIFFERENT_PARENT_AND_SUPPORTING_KEYS) {
5639 const dd::Index *old_sk =
5640 find_fk_supporting_key(hton, old_fk_table, *old_fk);
5641 const dd::Index *old_pk =
5642 find_fk_parent_key(hton, old_sk, old_fk_table, *old_fk);
5643
5644 if (old_sk != nullptr && old_pk != nullptr) {
5645 if (my_strcasecmp(system_charset_info, supporting_key->name,
5646 old_sk->name().c_str()) == 0) {
5647 dropped_key = old_pk->name().c_str();
5648 auto renamed_to_sk = [supporting_key](const Alter_rename_key *key) {
5649 return (my_strcasecmp(system_charset_info, supporting_key->name,
5650 key->new_name) == 0);
5651 };
5652 if (std::any_of(alter_info->alter_rename_key_list.begin(),
5653 alter_info->alter_rename_key_list.end(),
5654 renamed_to_sk)) {
5655 dropped_key = old_sk->name().c_str();
5656 }
5657 } else {
5658 dropped_key = old_sk->name().c_str();
5659 auto renamed_from_sk = [old_sk](const Alter_rename_key *key) {
5660 return (my_strcasecmp(system_charset_info, old_sk->name().c_str(),
5661 key->old_name) == 0);
5662 };
5663 if (std::any_of(alter_info->alter_rename_key_list.begin(),
5664 alter_info->alter_rename_key_list.end(),
5665 renamed_from_sk)) {
5666 dropped_key = old_pk->name().c_str();
5667 }
5668 }
5669 }
5670 } else {
5671 const dd::Index *old_pk =
5672 find_fk_parent_key(hton, nullptr, old_fk_table, *old_fk);
5673 if (old_pk) dropped_key = old_pk->name().c_str();
5674 }
5675
5676 my_error(ER_DROP_INDEX_FK, MYF(0), dropped_key);
5677 }
5678 1 return true;
5679 }
5680
5681 /**
5682 Find supporting key for the foreign key.
5683
5684 @param hton Handlerton for table's storage engine.
5685 @param alter_info Alter_info object describing child table.
5686 @param key_info_buffer Array describing keys in child table.
5687 @param key_count Number of keys in child table.
5688 @param fk FOREIGN_KEY object describing the FK.
5689
5690 @sa find_fk_supporting_key(handlerton*, const dd::Table*,
5691 const dd::Foreign_key*)
5692
5693 @retval non-nullptr - pointer to KEY object describing supporting key.
5694 @retval nullptr - if no supporting key were found.
5695 */
5696 613054 static const KEY *find_fk_supporting_key(handlerton *hton,
5697 Alter_info *alter_info,
5698 const KEY *key_info_buffer,
5699 const uint key_count,
5700 const FOREIGN_KEY *fk) {
5701 613054 uint best_match_count = 0;
5702 613054 const KEY *best_match_key = nullptr;
5703
5704 1945548 auto fk_columns_lambda = [fk](uint i) { return fk->key_part[i].str; };
5705
5706
2/2
✓ Branch 0 taken 1945155 times.
✓ Branch 1 taken 15 times.
1945170 for (const KEY *key = key_info_buffer; key < key_info_buffer + key_count;
5707 key++) {
5708 // We can't use FULLTEXT or SPATIAL indexes.
5709
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1945150 times.
1945155 if (key->flags & (HA_FULLTEXT | HA_SPATIAL)) continue;
5710
5711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1945150 times.
1945150 if (key->algorithm == HA_KEY_ALG_HASH) {
5712 if (hton->foreign_keys_flags & HTON_FKS_WITH_SUPPORTING_HASH_KEYS) {
5713 /*
5714 Storage engine supports hash keys as supporting keys for foreign
5715 keys. Hash key should contain all foreign key columns and only
5716 them (although in any order).
5717 Example: NDB and unique/primary key with USING HASH clause.
5718 */
5719 if (fk_is_key_exact_match_any_order(alter_info, fk->key_parts,
5720 fk_columns_lambda, key))
5721 return key;
5722 }
5723 } else {
5724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1945150 times.
1945150 if (hton->foreign_keys_flags & HTON_FKS_WITH_ANY_PREFIX_SUPPORTING_KEYS) {
5725 /*
5726 Storage engine supports non-hash keys which have common prefix
5727 with the foreign key as supporting keys for it. If there are
5728 several such keys, one which shares biggest prefix with FK is
5729 chosen.
5730
5731 Example: NDB and non-unique keys, or unique/primary keys without
5732 explicit USING HASH clause.
5733 */
5734 uint match_count = fk_key_prefix_match_count(
5735 alter_info, fk->key_parts, fk_columns_lambda, key, nullptr);
5736
5737 if (match_count > best_match_count) {
5738 best_match_count = match_count;
5739 best_match_key = key;
5740 }
5741 } else {
5742 /*
5743 Default case. Storage engine supports non-hash keys which contain
5744 full foreign key as prefix as supporting key for it.
5745 Example: InnoDB.
5746
5747 SQL-layer tries to automatically create such generated key when
5748 foreign key is created.
5749 */
5750
3/4
✓ Branch 0 taken 1945150 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 613039 times.
✓ Branch 3 taken 1332111 times.
1945150 if (fk_key_is_full_prefix_match(alter_info, fk->key_parts,
5751 fk_columns_lambda, key, nullptr))
5752 613039 return key;
5753 }
5754 }
5755 }
5756 15 return best_match_key;
5757 }
5758
5759 /**
5760 Make old table definition's foreign keys use temporary names.
5761 This is needed to avoid problems with duplicate foreign key
5762 names while we have two definitions of the same table.
5763
5764 @param thd Thread context.
5765 @param db_name Database where old table definition resides.
5766 @param backup_name Temporary name assigned to old table definition
5767 during ALTER TABLE.
5768
5769 @returns False - Success, True - Failure.
5770 */
5771
5772 48 static bool adjust_foreign_key_names_for_old_table_version(
5773 THD *thd, const char *db_name, const char *backup_name) {
5774 48 dd::Table *table_def = nullptr;
5775
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 MDL_request_list mdl_requests;
5776
5777
4/8
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 48 times.
48 if (thd->dd_client()->acquire_for_modification(db_name, backup_name,
5778 &table_def))
5779 return true;
5780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 assert(table_def != nullptr);
5781
5782
6/10
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 57 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 57 times.
✓ Branch 9 taken 48 times.
105 for (dd::Foreign_key *fk : *table_def->foreign_keys()) {
5783 char temp_fk_name[4 + 20 + 1];
5784
5785 114 snprintf(temp_fk_name, sizeof(temp_fk_name), "#fk_%llu",
5786
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 (ulonglong)fk->id());
5787
5788 /*
5789 Acquire metadata locks on temporary names before updating data-dictionary
5790 just in case somebody tries to create foreign keys with names like
5791 #fk_<number> concurrently.
5792 */
5793
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 MDL_request *mdl_request = new (thd->mem_root) MDL_request;
5794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (mdl_request == nullptr) return true;
5795
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 MDL_REQUEST_INIT(mdl_request, MDL_key::FOREIGN_KEY, db_name, temp_fk_name,
5796 MDL_EXCLUSIVE, MDL_STATEMENT);
5797
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 mdl_requests.push_front(mdl_request);
5798
5799 // Update dd::Foreign_key object but do not store it in data-dictionary yet.
5800
2/4
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
57 fk->set_name(temp_fk_name);
5801 }
5802
5803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 assert(!mdl_requests.is_empty());
5804
5805
2/4
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
48 if (thd->mdl_context.acquire_locks(&mdl_requests,
5806 thd->variables.lock_wait_timeout))
5807 return true;
5808
5809
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 return thd->dd_client()->update(table_def);
5810 }
5811
5812 /**
5813 Find max value of number component among existing generated foreign
5814 key names for the table.
5815
5816 @param table_name Table name (should be already in lowercase
5817 if l_c_t_n > 0).
5818 @param table_def Table definition.
5819 @param hton Table storage engine.
5820
5821 @note We assume that generated names follow pattern:
5822 (table name)(SE-specific or default FK name suffix)(number)
5823 E.g. "table_name_ibfk_####" for InnoDB. This function is in sync
5824 with generate_fk_name() and dd::rename_foreign_keys().
5825
5826 @note This function mimics dict_table_get_highest_foreign_id() from 5.7.
5827 */
5828
5829 145969 static uint get_fk_max_generated_name_number(const char *table_name,
5830 const dd::Table *table_def,
5831 handlerton *hton) {
5832 145969 uint key_number = 0;
5833 /*
5834 There is no need to lowercase table_name as it is already supposed
5835 to be in lowercase.
5836 */
5837 145969 size_t table_name_length = strlen(table_name);
5838
5839 145969 const LEX_CSTRING &fk_name_suffix =
5840
2/2
✓ Branch 0 taken 129315 times.
✓ Branch 1 taken 16654 times.
145969 hton->fk_name_suffix.str ? hton->fk_name_suffix : FK_NAME_DEFAULT_SUFFIX;
5841
5842
6/10
✓ Branch 0 taken 145969 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 145969 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 145969 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 642 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 642 times.
✓ Branch 9 taken 145969 times.
146611 for (const dd::Foreign_key *fk : table_def->foreign_keys()) {
5843 /*
5844 We assume that the name is generated if it starts with:
5845 <table_name><SE-specific or default FK name suffix>
5846
5847 Note that unlike during RENAME TABLE handling, here, i.e. when
5848 generating name for new constraints, we mimic InnoDB's behavior from
5849 5.7 and ignore pre-existing generated names which have pre-4.0.18 format.
5850 */
5851
1/2
✓ Branch 0 taken 642 times.
✗ Branch 1 not taken.
642 if (dd::is_generated_foreign_key_name(table_name, table_name_length, hton,
5852
4/4
✓ Branch 0 taken 233 times.
✓ Branch 1 taken 409 times.
✓ Branch 2 taken 229 times.
✓ Branch 3 taken 413 times.
875 *fk) &&
5853
3/4
✓ Branch 0 taken 233 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 229 times.
✓ Branch 3 taken 4 times.
233 (fk->name().c_str()[table_name_length + fk_name_suffix.length] !=
5854 '0')) {
5855 229 char *end = nullptr;
5856 229 uint nr = my_strtoull(
5857
1/2
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
229 fk->name().c_str() + table_name_length + fk_name_suffix.length, &end,
5858 229 10);
5859
2/4
✓ Branch 0 taken 229 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 229 times.
✗ Branch 3 not taken.
229 if (!*end && nr > key_number) key_number = nr;
5860 }
5861 }
5862 145969 return key_number;
5863 }
5864
5865 /**
5866 Generate a foreign key name and store it in buffer provided.
5867
5868 @note Foreign key names have to be unique for a given schema.
5869 This function is used when the user has not specified
5870 neither constraint name nor foreign key name.
5871
5872 @note We generated names according to the pattern:
5873 (table name)(SE-specific or default FK name suffix)(counter)
5874 The counter is 1-based and per table. The number chosen for the
5875 counter is 1 higher than the highest number currently in use.
5876 For InnoDB "_ibfk_" is used as suffix, so names are compatible
5877 with names generated by InnoDB in 5.7. For NDB, suffix "_fk_"
5878 is used and compatibility is not preserved (as in 5.7 NDB
5879 uses radically different approach anyway).
5880
5881 @param name_buff Buffer for generated name.
5882 @param name_buff_size Size of name buffer, if buffer
5883 is too small generated name
5884 will be truncated.
5885 @param table_name Table name.
5886 @param hton Table storage engine.
5887 @param[in,out] fk_max_generated_name_number Max value of number component
5888 among existing generated
5889 foreign key names.
5890 */
5891
5892 1224275 static void generate_fk_name(char *name_buff, size_t name_buff_size,
5893 const char *table_name, handlerton *hton,
5894 uint *fk_max_generated_name_number) {
5895 1224275 snprintf(name_buff, name_buff_size, "%s%s%u", table_name,
5896 1224275 (hton->fk_name_suffix.str ? hton->fk_name_suffix.str
5897 : FK_NAME_DEFAULT_SUFFIX.str),
5898
2/2
✓ Branch 0 taken 1224267 times.
✓ Branch 1 taken 8 times.
1224275 ++*fk_max_generated_name_number);
5899 1224275 }
5900
5901 /**
5902 Generate a foreign key name, allocate memory from thread's current
5903 memory root for it.
5904
5905 @note Foreign key names have to be unique for a given schema.
5906 This function is used when the user has not specified
5907 neither constraint name nor foreign key name.
5908
5909 @note We generated names according to the pattern:
5910 (table name)(SE-specific or default FK name suffix)(counter)
5911 The counter is 1-based and per table. The number chosen for the
5912 counter is 1 higher than the highest number currently in use.
5913 For InnoDB "_ibfk_" is used as suffix, so names are compatible
5914 with names generated by InnoDB in 5.7. For NDB, suffix "_fk_"
5915 is used and compatibility is not preserved (as in 5.7 NDB
5916 uses radically different approach anyway).
5917
5918 @param table_name Table name.
5919 @param hton Table storage engine.
5920 @param[in,out] fk_max_generated_name_number Max value of number component
5921 among existing generated foreign
5922 key names.
5923
5924 @retval Generated name
5925 */
5926
5927 612137 static const char *generate_fk_name(const char *table_name, handlerton *hton,
5928 uint *fk_max_generated_name_number) {
5929 // The below buffer should be sufficient for any generated name.
5930 char name[NAME_LEN + MAX_FK_NAME_SUFFIX_LENGTH + 10 + 1];
5931 612137 generate_fk_name(name, sizeof(name), table_name, hton,
5932 fk_max_generated_name_number);
5933
1/2
✓ Branch 0 taken 612137 times.
✗ Branch 1 not taken.
1224274 return sql_strdup(name);
5934 }
5935
5936 /**
5937 Check if candidate parent/supporting key contains exactly the same
5938 columns as the foreign key, possibly, in different order. Also check
5939 that columns usage by key is acceptable, i.e. key is not over column
5940 prefix.
5941
5942 @tparam F Function class which returns foreign key's
5943 referenced or referencing (depending on whether
5944 we check candidate parent or supporting key)
5945 column name by its index.
5946 @param fk_col_count Number of columns in the foreign key.
5947 @param fk_columns Object of F type bound to the specific foreign key
5948 for which parent/supporting key check is carried
5949 out.
5950 @param idx dd::Index object describing candidate parent/
5951 supporting key.
5952
5953 @sa fk_is_key_exact_match_any_order(Alter_info, uint, F, KEY).
5954
5955 @retval True - Key is proper parent/supporting key for the foreign key.
5956 @retval False - Key can't be parent/supporting key for the foreign key.
5957 */
5958 template <class F>
5959 static bool fk_is_key_exact_match_any_order(uint fk_col_count,
5960 const F &fk_columns,
5961 const dd::Index *idx) {
5962 /*
5963 Skip keys which have less elements (including hidden ones)
5964 than foreign key right away.
5965 */
5966 if (fk_col_count > idx->elements().size()) return false;
5967
5968 uint col_matched = 0;
5969
5970 for (const dd::Index_element *idx_el : idx->elements()) {
5971 if (idx_el->is_hidden()) continue;
5972
5973 uint j = 0;
5974 while (j < fk_col_count) {
5975 if (my_strcasecmp(system_charset_info, idx_el->column().name().c_str(),
5976 fk_columns(j)) == 0)
5977 break;
5978 j++;
5979 }
5980 if (j == fk_col_count) return false;
5981
5982 /*
5983 Foreign keys over virtual columns are not allowed.
5984 This is checked at earlier stage.
5985 */
5986 assert(!idx_el->column().is_virtual());
5987
5988 /*
5989 Prefix keys are not allowed/considered non-matching.
5990
5991 There is a special provision which allows to treat unique keys on
5992 POINT and BLOB columns with prefix length equal to real column
5993 length as candidate/primary keys. However, since InnoDB doesn't
5994 allow columns of such types in FKs, we don't need similar provision
5995 here. So we can simply use dd::Index_element::is_prefix().
5996
5997 Calling Index_element::is_prefix() can be a bit expensive so
5998 we do this after checking if foreign key has matching column
5999 (foreign key column list is likely to be small).
6000 */
6001 if (idx_el->is_prefix()) return false;
6002
6003 ++col_matched;
6004 }
6005
6006 return (col_matched == fk_col_count);
6007 }
6008
6009 /**
6010 Count how many elements from the start of the candidate parent/supporting
6011 key match elements at the start of the foreign key (prefix parts are
6012 considered non-matching).
6013
6014 @tparam F Function class which returns foreign key's
6015 referenced or referencing (depending on whether
6016 we check candidate parent or supporting key)
6017 column name by its index.
6018 @param fk_col_count Number of columns in the foreign key.
6019 @param fk_columns Object of F type bound to the specific foreign key
6020 for which parent/supporting key check is carried
6021 out.
6022 @param idx dd::Index object describing candidate parent/
6023 supporting key.
6024 @param use_hidden Use hidden elements of the key as well.
6025
6026 @sa fk_key_prefix_match_count(Alter_info, uint, F, KEY, KEY).
6027
6028 @retval Number of matching columns.
6029 */
6030 template <class F>
6031 653608 static uint fk_key_prefix_match_count(uint fk_col_count, const F &fk_columns,
6032 const dd::Index *idx, bool use_hidden) {
6033 653608 uint fk_col_idx = 0;
6034
6035
6/10
✓ Branch 0 taken 326804 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326804 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 326804 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 653789 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 653789 times.
✓ Branch 9 taken 62 times.
1961310 for (const dd::Index_element *idx_el : idx->elements()) {
6036
2/2
✓ Branch 0 taken 326444 times.
✓ Branch 1 taken 327345 times.
1307578 if (fk_col_idx == fk_col_count) break;
6037
6038
5/8
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 327237 times.
✓ Branch 2 taken 108 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 108 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 327345 times.
654690 if (!use_hidden && idx_el->is_hidden()) continue;
6039
6040
7/12
✓ Branch 0 taken 1548 times.
✓ Branch 1 taken 325797 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1548 times.
✓ Branch 4 taken 325797 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1548 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 325797 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1548 times.
✗ Branch 11 not taken.
654690 if (my_strcasecmp(system_charset_info, idx_el->column().name().c_str(),
6041
2/2
✓ Branch 0 taken 298 times.
✓ Branch 1 taken 327047 times.
654690 fk_columns(fk_col_idx)) != 0)
6042 596 break;
6043
6044 /*
6045 Foreign keys over virtual columns are not allowed.
6046 This is checked at earlier stage.
6047 */
6048
3/6
✓ Branch 0 taken 327047 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 327047 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 327047 times.
654094 assert(!idx_el->column().is_virtual());
6049
6050 /*
6051 Prefix parts are considered non-matching.
6052
6053 There is a special provision which allows to treat unique keys on
6054 POINT and BLOB columns with prefix length equal to real column
6055 length as candidate/primary keys. However, since InnoDB doesn't
6056 allow columns of such types in FKs, we don't need similar provision
6057 here. So we can simply use dd::Index_element::is_prefix().
6058
6059 Calling Index_element::is_prefix() can be a bit expensive so
6060 we do this after checking column name.
6061
6062 InnoDB doesn't set correct length for hidden index elements so
6063 we simply assume that they use the full columns. We avoid calling
6064 this code when it is not correct, see find_fk_parent_key().
6065 */
6066
6/10
✓ Branch 0 taken 327047 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326997 times.
✓ Branch 3 taken 50 times.
✓ Branch 4 taken 326997 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 326997 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 327047 times.
654094 if (!idx_el->is_hidden() && idx_el->is_prefix()) break;
6067
6068 654094 ++fk_col_idx;
6069 }
6070
6071 653608 return fk_col_idx;
6072 }
6073
6074 /**
6075 Check if candidate parent/supporting key contains all columns from the
6076 foreign key at its start and in the same order it is in the foreign key.
6077 Also check that columns usage by key is acceptable, i.e. key is not over
6078 column prefix.
6079
6080 @tparam F Function class which returns foreign key's
6081 referenced or referencing (depending on whether
6082 we check candidate parent or supporting key)
6083 column name by its index.
6084 @param fk_col_count Number of columns in the foreign key.
6085 @param fk_columns Object of F type bound to the specific foreign key
6086 for which parent/supporting key check is carried
6087 out.
6088 @param idx dd::Index object describing candidate parent/
6089 supporting key.
6090 @param use_hidden Use hidden elements of the key as well.
6091
6092 @sa fk_key_is_full_prefix_match(Alter_info, uint, F, KEY, KEY).
6093
6094 @retval True - Key is proper parent/supporting key for the foreign key.
6095 @retval False - Key can't be parent/supporting key for the foreign key.
6096 */
6097 template <class F>
6098 653608 static bool fk_key_is_full_prefix_match(uint fk_col_count, const F &fk_columns,
6099 const dd::Index *idx, bool use_hidden) {
6100 // The index must have at least same amount of elements as the foreign key.
6101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 326804 times.
653608 if (fk_col_count > idx->elements().size()) return false;
6102
6103 uint match_count =
6104 653608 fk_key_prefix_match_count(fk_col_count, fk_columns, idx, use_hidden);
6105
6106 653608 return (match_count == fk_col_count);
6107 }
6108
6109 /**
6110 Find parent key which matches the foreign key. Prefer unique key if possible.
6111
6112 @tparam F Function class which returns foreign key's column
6113 name by its index.
6114 @param hton Handlerton for tables' storage engine. Used to
6115 figure out what kind of parent keys are supported
6116 by the storage engine..
6117 @param supporting_key Supporting key of the child. Needed to skip
6118 supporting keys as candidate parent keys for
6119 self referencing FKs.
6120 @param parent_table_def dd::Table object describing the parent table.
6121 @param fk_col_count Number of columns in the foreign key.
6122 @param fk_columns Object of F type bound to the specific foreign key
6123 for which parent key check is carried out.
6124
6125 @retval non-nullptr - pointer to dd::Index object describing the parent key.
6126 @retval nullptr - if no parent key were found.
6127 */
6128 template <class F>
6129 652980 static const dd::Index *find_fk_parent_key(handlerton *hton,
6130 const dd::Index *supporting_key,
6131 const dd::Table *parent_table_def,
6132 uint fk_col_count,
6133 const F &fk_columns) {
6134 652980 bool use_hidden = false;
6135
6136
1/2
✓ Branch 0 taken 326490 times.
✗ Branch 1 not taken.
652980 if (hton->foreign_keys_flags & HTON_FKS_WITH_EXTENDED_PARENT_KEYS) {
6137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 326490 times.
652980 assert(hton->foreign_keys_flags & HTON_FKS_WITH_PREFIX_PARENT_KEYS);
6138 /*
6139 Engine considers hidden part of key (columns from primary key
6140 which are implicitly added to secondary keys) when determines
6141 if it can serve as parent. Example: InnoDB.
6142
6143 Note that InnoDB doesn't correctly set length of these hidden
6144 elements of keys, so we assume that they always cover the whole
6145 column. To be able to do this we need to exclude primary keys
6146 with prefix elements [sic!] from consideration. This means that
6147 we won't support some exotic parent key scenarios which were
6148 supported in 5.7. For example:
6149
6150 CREATE TABLE t1 (a INT, b CHAR(100), c int, KEY(c),
6151 PRIMARY KEY (a, b(10)));
6152 CREATE TABLE t2 (fk1 int, fk2 int,
6153 FOREIGN KEY (fk1, fk2) REFERENCES t1 (c, a));
6154 */
6155 dd::Table::Index_collection::const_iterator first_idx_it =
6156
3/6
✓ Branch 0 taken 326490 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326490 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 326490 times.
✗ Branch 5 not taken.
652980 std::find_if(parent_table_def->indexes().cbegin(),
6157
2/4
✓ Branch 0 taken 326490 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326490 times.
✗ Branch 3 not taken.
652980 parent_table_def->indexes().cend(),
6158 326561 [](const dd::Index *i) { return !i->is_hidden(); });
6159
6160
4/6
✓ Branch 0 taken 326490 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326490 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 326484 times.
✓ Branch 5 taken 6 times.
652980 if (first_idx_it != parent_table_def->indexes().cend()) {
6161 /*
6162 Unlike similar check in prepare_self_ref_fk_parent_key() call
6163 to dd::Index::is_candidate_key() is not cheap, so we try to
6164 avoid it unless absolutely necessary. As result we try to use
6165 hidden columns even for tables without implicit primary key,
6166 which works fine (since such tables won't have any hidden
6167 columns matching foreign key columns).
6168 */
6169
5/8
✓ Branch 0 taken 326484 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326484 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 326375 times.
✓ Branch 5 taken 109 times.
✓ Branch 6 taken 326484 times.
✗ Branch 7 not taken.
1305718 if ((*first_idx_it)->type() != dd::Index::IT_PRIMARY ||
6170
3/6
✓ Branch 0 taken 326375 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326375 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 326375 times.
✗ Branch 5 not taken.
652750 (*first_idx_it)->is_candidate_key())
6171 652968 use_hidden = true;
6172 }
6173 }
6174
6175
6/10
✓ Branch 0 taken 326490 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326490 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 326490 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 326793 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 326793 times.
✓ Branch 9 taken 20 times.
1306606 for (const dd::Index *idx : parent_table_def->indexes()) {
6176 // We can't use FULLTEXT or SPATIAL indexes.
6177
3/6
✓ Branch 0 taken 326793 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326793 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 326793 times.
1307172 if (idx->type() == dd::Index::IT_FULLTEXT ||
6178
2/4
✓ Branch 0 taken 326793 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 326793 times.
653586 idx->type() == dd::Index::IT_SPATIAL)
6179 continue;
6180
6181
1/2
✓ Branch 0 taken 326793 times.
✗ Branch 1 not taken.
653586 if (hton->foreign_keys_flags &
6182 HTON_FKS_NEED_DIFFERENT_PARENT_AND_SUPPORTING_KEYS) {
6183 /*
6184 The storage engine does not support using the same index for both the
6185 supporting index and the parent index. In this case, the supporting
6186 index cannot be a candidate parent index, and must be skipped.
6187 */
6188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 326793 times.
653586 if (idx == supporting_key) continue;
6189 }
6190
6191 // We also can't use hidden indexes.
6192
3/4
✓ Branch 0 taken 326793 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
✓ Branch 3 taken 326716 times.
653586 if (idx->is_hidden()) continue;
6193
6194
1/2
✓ Branch 0 taken 326716 times.
✗ Branch 1 not taken.
653432 if (hton->foreign_keys_flags & HTON_FKS_WITH_PREFIX_PARENT_KEYS) {
6195 /*
6196 Engine supports unique and non unique-parent keys which contain full
6197 foreign key as its prefix. Example: InnoDB.
6198
6199 Primary and unique keys are sorted before non-unique keys.
6200 So if there is suitable unique parent key we will always find
6201 it before any non-unique key.
6202 */
6203
6204
3/4
✓ Branch 0 taken 326716 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326470 times.
✓ Branch 3 taken 246 times.
653432 if (fk_key_is_full_prefix_match(fk_col_count, fk_columns, idx,
6205 use_hidden))
6206 652940 return idx;
6207 } else {
6208 /*
6209 Default case. Engine only supports unique parent keys which
6210 contain exactly the same columns as foreign key, possibly
6211 in different order. Example: NDB.
6212 */
6213 if ((idx->type() == dd::Index::IT_PRIMARY ||
6214 idx->type() == dd::Index::IT_UNIQUE) &&
6215 fk_is_key_exact_match_any_order(fk_col_count, fk_columns, idx))
6216 return idx;
6217 }
6218 }
6219 40 return nullptr;
6220 }
6221
6222 /**
6223 Find supporting key for the foreign key.
6224
6225 @param hton Handlerton for tables' storage engine. Used to
6226 figure out what kind of supporting keys are
6227 allowed by the storage engine.
6228 @param table_def dd::Table object describing the child table.
6229 @param fk dd::Foreign_key object describing the foreign
6230 key.
6231
6232 @sa find_fk_supporting_key(handlerton*, Alter_info*, const KEY*, uint,
6233 const FOREIGN_KEY*)
6234
6235 @retval non-nullptr - pointer to dd::Index object describing supporting key.
6236 @retval nullptr - if no supporting key were found.
6237 */
6238 36 static const dd::Index *find_fk_supporting_key(handlerton *hton,
6239 const dd::Table *table_def,
6240 const dd::Foreign_key *fk) {
6241 36 uint best_match_count = 0;
6242 36 const dd::Index *best_match_idx = nullptr;
6243
6244 108 auto fk_columns_lambda = [fk](uint i) {
6245 108 return fk->elements()[i]->column().name().c_str();
6246 36 };
6247
6248
5/10
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 96 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 96 times.
✗ Branch 9 not taken.
96 for (const dd::Index *idx : table_def->indexes()) {
6249 // We can't use FULLTEXT or SPATIAL indexes.
6250
4/6
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 95 times.
192 if (idx->type() == dd::Index::IT_FULLTEXT ||
6251
3/4
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 95 times.
96 idx->type() == dd::Index::IT_SPATIAL)
6252 1 continue;
6253
6254 // We also can't use hidden indexes.
6255
3/4
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 88 times.
95 if (idx->is_hidden()) continue;
6256
6257
2/4
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 88 times.
88 if (idx->algorithm() == dd::Index::IA_HASH) {
6258 if (hton->foreign_keys_flags & HTON_FKS_WITH_SUPPORTING_HASH_KEYS) {
6259 /*
6260 Storage engine supports hash keys as supporting keys for foreign
6261 keys. Hash key should contain all foreign key columns and only
6262 them (although in any order).
6263 Example: NDB and unique/primary key with USING HASH clause.
6264 */
6265 if (fk_is_key_exact_match_any_order(fk->elements().size(),
6266 fk_columns_lambda, idx))
6267 36 return idx;
6268 }
6269 } else {
6270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (hton->foreign_keys_flags & HTON_FKS_WITH_ANY_PREFIX_SUPPORTING_KEYS) {
6271 /*
6272 Storage engine supports non-hash keys which have common prefix
6273 with the foreign key as supporting keys for it. If there are
6274 several such keys, one which shares biggest prefix with FK is
6275 chosen.
6276
6277 Example: NDB and non-unique keys, or unique/primary keys without
6278 explicit USING HASH clause.
6279 */
6280 uint match_count = fk_key_prefix_match_count(
6281 fk->elements().size(), fk_columns_lambda, idx, false);
6282
6283 if (match_count > best_match_count) {
6284 best_match_count = match_count;
6285 best_match_idx = idx;
6286 }
6287 } else {
6288 /*
6289 Default case. Storage engine supports non-hash keys which contain
6290 full foreign key as prefix as supporting key for it.
6291 Example: InnoDB.
6292
6293 SQL-layer tries to automatically create such generated key when
6294 foreign key is created.
6295 */
6296
4/6
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
✓ Branch 5 taken 52 times.
88 if (fk_key_is_full_prefix_match(fk->elements().size(),
6297 fk_columns_lambda, idx, false))
6298 36 return idx;
6299 }
6300 }
6301 }
6302 return best_match_idx;
6303 }
6304
6305 /*
6306 Check if parent key for foreign key exists, set foreign key's unique
6307 constraint name accordingly. Emit error if no parent key found.
6308
6309 @note Prefer unique key if possible. If parent key is non-unique
6310 unique constraint name is set to NULL.
6311
6312 @note CREATE TABLE and ALTER TABLE code use this function for
6313 non-self-referencing foreign keys.
6314
6315 @sa prepare_fk_parent_key(handlerton, dd::Table, dd::Table, dd::Table,
6316 dd::Foreign_key)
6317
6318 @param hton Handlerton for tables' storage engine.
6319 @param parent_table_def dd::Table object describing parent table.
6320 @param fk[in,out] FOREIGN_KEY object describing the FK, its
6321 unique_index_name member will be updated
6322 if matching unique constraint is found.
6323
6324 @retval Operation result. False if success.
6325 */
6326 325232 static bool prepare_fk_parent_key(handlerton *hton,
6327 const dd::Table *parent_table_def,
6328 FOREIGN_KEY *fk) {
6329 325797 auto fk_columns_lambda = [fk](uint i) { return fk->fk_key_part[i].str; };
6330
6331 /*
6332 Here, it is safe to pass nullptr as supporting key, since this
6333 function is not called for self referencing foreign keys.
6334 */
6335
1/2
✓ Branch 0 taken 325232 times.
✗ Branch 1 not taken.
325232 const dd::Index *parent_key = find_fk_parent_key(
6336 hton, nullptr, parent_table_def, fk->key_parts, fk_columns_lambda);
6337
6338
2/2
✓ Branch 0 taken 325220 times.
✓ Branch 1 taken 12 times.
325232 if (parent_key != nullptr) {
6339 /*
6340 We only store names of PRIMARY/UNIQUE keys in unique_index_name,
6341 even though InnoDB allows non-unique indexes as parent keys.
6342 */
6343
5/6
✓ Branch 0 taken 325220 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 152 times.
✓ Branch 3 taken 325068 times.
✓ Branch 4 taken 325104 times.
✓ Branch 5 taken 116 times.
325372 if (parent_key->type() == dd::Index::IT_PRIMARY ||
6344
3/4
✓ Branch 0 taken 152 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 116 times.
152 parent_key->type() == dd::Index::IT_UNIQUE) {
6345
1/2
✓ Branch 0 taken 325104 times.
✗ Branch 1 not taken.
325104 fk->unique_index_name = parent_key->name().c_str();
6346 } else {
6347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 116 times.
116 assert(fk->unique_index_name == nullptr);
6348 }
6349 325220 return false;
6350 }
6351
6352
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 my_error(ER_FK_NO_INDEX_PARENT, MYF(0), fk->name, fk->ref_table.str);
6353 12 return true;
6354 }
6355
6356 /**
6357 Find parent key which matches the foreign key. Prefer unique key if possible.
6358
6359 @param hton Handlerton for tables' storage engine.
6360 @param supporting_key Supporting key of the child. Needed to skip
6361 supporting keys as candidate parent keys for
6362 self referencing FKs.
6363 @param parent_table_def dd::Table object describing the parent table.
6364 @param fk dd::Foreign_key object describing the foreign key.
6365
6366 @retval non-nullptr - pointer to dd::Index object describing the parent key.
6367 @retval nullptr - if no parent key were found.
6368 */
6369 1258 static const dd::Index *find_fk_parent_key(handlerton *hton,
6370 const dd::Index *supporting_key,
6371 const dd::Table *parent_table_def,
6372 const dd::Foreign_key *fk) {
6373 1440 auto fk_columns_lambda = [fk](uint i) {
6374 1440 return fk->elements()[i]->referenced_column_name().c_str();
6375 1258 };
6376
1/2
✓ Branch 0 taken 1258 times.
✗ Branch 1 not taken.
1258 return find_fk_parent_key(hton, supporting_key, parent_table_def,
6377
1/2
✓ Branch 0 taken 1258 times.
✗ Branch 1 not taken.
3774 fk->elements().size(), fk_columns_lambda);
6378 }
6379
6380 1253 bool prepare_fk_parent_key(handlerton *hton, const dd::Table *parent_table_def,
6381 const dd::Table *old_parent_table_def,
6382 const dd::Table *old_child_table_def,
6383 bool is_self_referencing_fk, dd::Foreign_key *fk) {
6384 1253 const dd::Index *supporting_key = nullptr;
6385
6386 /*
6387 For self referencing foreign keys, we should identify the supporting
6388 key to make sure it is not considered as a candidate parent key,
6389 unless the SE supports this. This function will be called for self
6390 referencing foreign keys only during upgrade from 5.7.
6391 */
6392
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 1231 times.
1253 if (is_self_referencing_fk &&
6393
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 (hton->foreign_keys_flags &
6394 HTON_FKS_NEED_DIFFERENT_PARENT_AND_SUPPORTING_KEYS)) {
6395 22 supporting_key = find_fk_supporting_key(hton, parent_table_def, fk);
6396 }
6397
6398 const dd::Index *parent_key =
6399 1253 find_fk_parent_key(hton, supporting_key, parent_table_def, fk);
6400
6401
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1245 times.
1253 if (parent_key == nullptr) {
6402 // No matching parent key in new table definition.
6403
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 if (old_parent_table_def == nullptr) {
6404 /*
6405 No old version of parent table definition. This must be CREATE
6406 TABLE or RENAME TABLE (or possibly ALTER TABLE RENAME).
6407 */
6408 3 my_error(ER_FK_NO_INDEX_PARENT, MYF(0), fk->name().c_str(),
6409 3 fk->referenced_table_name().c_str());
6410 } else {
6411 /*
6412 This is ALTER TABLE which dropped parent key.
6413
6414 To report error we find original foreign key definition first.
6415 */
6416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 assert(old_child_table_def != nullptr);
6417 16 auto same_name = [fk](const dd::Foreign_key *el) {
6418 8 return my_strcasecmp(system_charset_info, fk->name().c_str(),
6419 8 el->name().c_str()) == 0;
6420 5 };
6421 auto old_fk =
6422
3/6
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
5 std::find_if(old_child_table_def->foreign_keys().begin(),
6423
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 old_child_table_def->foreign_keys().end(), same_name);
6424
3/6
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
5 assert(old_fk != old_child_table_def->foreign_keys().end());
6425
6426 /*
6427 This function is normally called only for non-self referencing foreign
6428 keys. The only exception is during upgrade from 5.7, in which case
6429 old_parent_table_def == nullptr, which means that a different execution
6430 path is taken above. Hence, it is safe to submit nullptr as the
6431 supporting key in the call to find_fk_parent_key() below.
6432 */
6433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 assert(!is_self_referencing_fk);
6434
6435 /*
6436 And then try to find original parent key name. Just getting
6437 unique constraint name won't work for non-unique parent key.
6438 Ideally we should be using handlerton of old table version
6439 below, however, in practice, new table version's handlerton
6440 works just fine, since we do not allow changing of storage
6441 engines for tables with foreign keys.
6442 */
6443 const dd::Index *old_pk =
6444
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 find_fk_parent_key(hton, nullptr, old_parent_table_def, *old_fk);
6445
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
10 my_error(ER_DROP_INDEX_FK, MYF(0),
6446
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 old_pk ? old_pk->name().c_str() : "<unknown key name>");
6447 }
6448 8 return true;
6449 }
6450
6451 /*
6452 If parent key is not PRIMARY/UNIQUE set UNIQUE_CONSTRAINT_NAME to
6453 NULL value. This is done by setting the name to "", which is
6454 interpreted as NULL when it is stored to the DD tables.
6455 */
6456
4/4
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 1118 times.
✓ Branch 2 taken 1146 times.
✓ Branch 3 taken 99 times.
1372 if (parent_key->type() == dd::Index::IT_PRIMARY ||
6457
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 99 times.
127 parent_key->type() == dd::Index::IT_UNIQUE) {
6458
3/6
✓ Branch 0 taken 1146 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1146 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1146 times.
✗ Branch 5 not taken.
1146 fk->set_unique_constraint_name(parent_key->name().c_str());
6459 } else {
6460
2/4
✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
✗ Branch 3 not taken.
99 fk->set_unique_constraint_name("");
6461 }
6462
6463 1245 return false;
6464 }
6465
6466 /**
6467 Helper which builds Ha_fk_column_type describing column type from
6468 its Create_field object.
6469
6470 @sa fill_dd_columns_from_create_fields().
6471 */
6472
6473 350087 static void fill_ha_fk_column_type(Ha_fk_column_type *fk_column_type,
6474 const Create_field *field) {
6475 350087 fk_column_type->type = dd::get_new_field_type(field->sql_type);
6476 350087 fk_column_type->char_length = field->max_display_width_in_bytes();
6477 350087 fk_column_type->field_charset = field->charset;
6478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 350087 times.
350087 fk_column_type->elements_count = field->interval ? field->interval->count : 0;
6479 350087 fk_column_type->numeric_scale = 0;
6480 350087 dd::get_field_numeric_scale(field, &fk_column_type->numeric_scale);
6481 350087 fk_column_type->is_unsigned = field->is_unsigned;
6482 350087 }
6483
6484 /**
6485 Helper which builds Ha_fk_column_type describing column type from
6486 its dd::Column object.
6487 */
6488
6489 328019 static bool fill_ha_fk_column_type(Ha_fk_column_type *fk_column_type,
6490 const dd::Column *column) {
6491 328019 fk_column_type->type = column->type();
6492 328019 fk_column_type->char_length = column->char_length();
6493 328019 fk_column_type->field_charset = dd_get_mysql_charset(column->collation_id());
6494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 328019 times.
328019 if (fk_column_type->field_charset == nullptr) {
6495 my_printf_error(ER_UNKNOWN_COLLATION,
6496 "invalid collation id %llu for table %s, column %s", MYF(0),
6497 column->collation_id(), column->table().name().c_str(),
6498 column->name().c_str());
6499 return true;
6500 }
6501 328019 fk_column_type->elements_count = column->elements_count();
6502 328019 fk_column_type->numeric_scale = column->numeric_scale();
6503 328019 fk_column_type->is_unsigned = column->is_unsigned();
6504 328019 return false;
6505 }
6506
6507 /**
6508 Prepare FOREIGN_KEY struct with info about a foreign key.
6509
6510 @param thd Thread handle.
6511 @param create_info Create info from parser.
6512 @param alter_info Alter_info structure describing ALTER TABLE.
6513 @param db Database name.
6514 @param table_name Table name.
6515 @param is_partitioned Indicates whether table is partitioned.
6516 @param key_info_buffer Array of indexes.
6517 @param key_count Number of indexes.
6518 @param fk_info_all FOREIGN_KEY array with foreign keys which were
6519 already processed.
6520 @param fk_number Number of foreign keys which were already
6521 processed.
6522 @param se_supports_fks Indicates whether SE supports FKs.
6523 If not only basic FK validation is
6524 performed.
6525 @param find_parent_key Indicates whether we need to lookup name of unique
6526 constraint in parent table for the FK.
6527 @param[in,out] fk_key Parser info about new FK to
6528 prepare.
6529 @param[in,out] fk_max_generated_name_number Max value of number component
6530 among existing generated foreign
6531 key names.
6532 @param[out] fk_info Struct to populate.
6533
6534 @retval true if error (error reported), false otherwise.
6535 */
6536
6537 612874 static bool prepare_foreign_key(THD *thd, HA_CREATE_INFO *create_info,
6538 Alter_info *alter_info, const char *db,
6539 const char *table_name, bool is_partitioned,
6540 KEY *key_info_buffer, uint key_count,
6541 const FOREIGN_KEY *fk_info_all, uint fk_number,
6542 bool se_supports_fks, bool find_parent_key,
6543 Foreign_key_spec *fk_key,
6544 uint *fk_max_generated_name_number,
6545 FOREIGN_KEY *fk_info) {
6546
1/2
✓ Branch 0 taken 612874 times.
✗ Branch 1 not taken.
612874 DBUG_TRACE;
6547
6548 // FKs are not supported for temporary tables.
6549
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 612872 times.
612874 if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
6550
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_CANNOT_ADD_FOREIGN, MYF(0), table_name);
6551 2 return true;
6552 }
6553
6554 // FKs are not supported with CREATE TABLE ... START TRANSACTION.
6555
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 612871 times.
612872 if (create_info->m_transactional_ddl) {
6556
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_FOREIGN_KEY_WITH_ATOMIC_CREATE_SELECT, MYF(0));
6557 1 return true;
6558 }
6559
6560 // Validate checks (among other things) that index prefixes are
6561 // not used and that generated columns are not used with
6562 // SET NULL and ON UPDATE CASCASE. Since this cannot change once
6563 // the FK has been made, it is enough to check it for new FKs.
6564
3/4
✓ Branch 0 taken 612871 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 612852 times.
612871 if (fk_key->validate(thd, table_name, alter_info->create_list)) return true;
6565
6566
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 612818 times.
612852 if (!se_supports_fks) return false;
6567
6568
2/2
✓ Branch 0 taken 681 times.
✓ Branch 1 taken 612137 times.
612818 if (fk_key->has_explicit_name) {
6569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 681 times.
681 assert(fk_key->name.str);
6570 681 fk_info->name = fk_key->name.str;
6571 } else {
6572
1/2
✓ Branch 0 taken 612137 times.
✗ Branch 1 not taken.
612137 fk_info->name = generate_fk_name(table_name, create_info->db_type,
6573 fk_max_generated_name_number);
6574 /*
6575 Update Foreign_key_spec::name member as some storage engines
6576 (e.g. NDB) rely on this information. To make this safe for
6577 prepared statement re-execution we have to employ
6578 Foreign_key_spec::has_explicit_name. Solving this issue in a
6579 better way requires change of approach which NDB uses to get
6580 info about added foreign keys.
6581 */
6582
1/2
✓ Branch 0 taken 612137 times.
✗ Branch 1 not taken.
612137 fk_key->name.str = thd->stmt_arena->mem_strdup(fk_info->name);
6583 612137 fk_key->name.length = strlen(fk_info->name);
6584
6585 // Length of generated name should be checked as well.
6586
3/4
✓ Branch 0 taken 612137 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 612136 times.
612137 if (check_string_char_length(to_lex_cstring(fk_info->name), "",
6587 NAME_CHAR_LEN, system_charset_info, true)) {
6588
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_TOO_LONG_IDENT, MYF(0), fk_info->name);
6589 1 return true;
6590 }
6591 }
6592
6593 /*
6594 Check that we are not creating several foreign keys with the same
6595 name over same table. This is mostly to avoid expensive phases of
6596 ALTER TABLE in such a case. Without this check the problem will be
6597 detected at the later stage when info about foreign keys is stored
6598 in data-dictionary.
6599 */
6600
2/2
✓ Branch 0 taken 611719 times.
✓ Branch 1 taken 612812 times.
1224531 for (uint fk_idx = 0; fk_idx < fk_number; fk_idx++) {
6601
3/4
✓ Branch 0 taken 611719 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 611714 times.
611719 if (!my_strcasecmp(system_charset_info, fk_info_all[fk_idx].name,
6602 fk_info->name)) {
6603
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_error(ER_FK_DUP_NAME, MYF(0), fk_info->name);
6604 5 return true;
6605 }
6606 }
6607
6608 612812 fk_info->key_parts = fk_key->columns.size();
6609
6610 /*
6611 In --lower-case-table-names=2 mode we are to use lowercased versions of
6612 parent db and table names for acquiring MDL and lookup, but still need
6613 to store their original versions in the data-dictionary.
6614 */
6615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612812 times.
612812 if (lower_case_table_names == 2) {
6616 fk_info->ref_db = fk_key->orig_ref_db;
6617 fk_info->ref_table = fk_key->orig_ref_table;
6618 } else {
6619 612812 fk_info->ref_db = fk_key->ref_db;
6620 612812 fk_info->ref_table = fk_key->ref_table;
6621 }
6622
6623 612812 fk_info->delete_opt = fk_key->delete_opt;
6624 612812 fk_info->update_opt = fk_key->update_opt;
6625 612812 fk_info->match_opt = fk_key->match_opt;
6626
6627 612812 fk_info->key_part = reinterpret_cast<LEX_CSTRING *>(
6628
1/2
✓ Branch 0 taken 612812 times.
✗ Branch 1 not taken.
612812 thd->mem_calloc(sizeof(LEX_CSTRING) * fk_key->columns.size()));
6629 612812 fk_info->fk_key_part = reinterpret_cast<LEX_CSTRING *>(
6630
1/2
✓ Branch 0 taken 612812 times.
✗ Branch 1 not taken.
612812 thd->mem_calloc(sizeof(LEX_CSTRING) * fk_key->columns.size()));
6631
6632 612812 Prealloced_array<Create_field *, 1> referencing_fields(PSI_INSTRUMENT_ME);
6633
6634
2/2
✓ Branch 0 taken 613270 times.
✓ Branch 1 taken 612802 times.
1226072 for (size_t column_nr = 0; column_nr < fk_key->ref_columns.size();
6635 column_nr++) {
6636
1/2
✓ Branch 0 taken 613270 times.
✗ Branch 1 not taken.
613270 const Key_part_spec *col = fk_key->columns[column_nr];
6637
6638 /* Check that referencing column exists and is not virtual. */
6639
1/2
✓ Branch 0 taken 613270 times.
✗ Branch 1 not taken.
613270 List_iterator<Create_field> find_it(alter_info->create_list);
6640 Create_field *find;
6641
1/2
✓ Branch 0 taken 5173160 times.
✗ Branch 1 not taken.
5173160 while ((find = find_it++)) {
6642
1/2
✓ Branch 0 taken 5173160 times.
✗ Branch 1 not taken.
5173160 if (my_strcasecmp(system_charset_info, col->get_field_name(),
6643
2/2
✓ Branch 0 taken 613270 times.
✓ Branch 1 taken 4559890 times.
5173160 find->field_name) == 0) {
6644 613270 break;
6645 }
6646 }
6647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 613270 times.
613270 if (find == nullptr) {
6648 /*
6649 In practice this should not happen as wrong column name is caught
6650 during generated index processing and error with good enough message
6651 is reported. So we don't fuss about error message here.
6652 */
6653 my_error(ER_CANNOT_ADD_FOREIGN, MYF(0));
6654 10 return true;
6655 }
6656
6657
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 613267 times.
613270 if (find->is_virtual_gcol()) {
6658
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_FK_CANNOT_USE_VIRTUAL_COLUMN, MYF(0), fk_info->name,
6659 col->get_field_name());
6660 3 return true;
6661 }
6662
6663 /*
6664 Foreign keys with SET NULL as one of referential actions do not
6665 make sense if any of referencing columns are non-nullable, so
6666 we prohibit them.
6667 */
6668
2/2
✓ Branch 0 taken 613228 times.
✓ Branch 1 taken 39 times.
613267 if ((fk_info->delete_opt == FK_OPTION_SET_NULL ||
6669
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 613196 times.
613228 fk_info->update_opt == FK_OPTION_SET_NULL) &&
6670
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 70 times.
71 find->flags & NOT_NULL_FLAG) {
6671
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_FK_COLUMN_NOT_NULL, MYF(0), col->get_field_name(),
6672 fk_info->name);
6673 1 return true;
6674 }
6675
6676 /*
6677 Check constraints evaluation is done before writing row to the storage
6678 engine but foreign key referential actions SET NULL, UPDATE CASCADE and
6679 SET DEFAULT are executed by the engine. Check constraints can not be
6680 evaluated for the these foreign key referential actions, so prohibit
6681 them.
6682 */
6683
2/2
✓ Branch 0 taken 613228 times.
✓ Branch 1 taken 38 times.
613266 if (fk_info->delete_opt == FK_OPTION_SET_NULL ||
6684
1/2
✓ Branch 0 taken 613228 times.
✗ Branch 1 not taken.
613228 fk_info->delete_opt == FK_OPTION_DEFAULT ||
6685
2/2
✓ Branch 0 taken 613196 times.
✓ Branch 1 taken 32 times.
613228 fk_info->update_opt == FK_OPTION_SET_NULL ||
6686
1/2
✓ Branch 0 taken 613196 times.
✗ Branch 1 not taken.
613196 fk_info->update_opt == FK_OPTION_DEFAULT ||
6687
2/2
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 613008 times.
613196 fk_info->update_opt == FK_OPTION_CASCADE) {
6688
3/4
✓ Branch 0 taken 258 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 252 times.
267 for (auto &cc_spec : alter_info->check_constraint_spec_list) {
6689
3/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 9 times.
15 if (cc_spec->expr_refers_column(find->field_name)) {
6690 6 my_error(ER_CHECK_CONSTRAINT_CLAUSE_USING_FK_REFER_ACTION_COLUMN,
6691
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 MYF(0), find->field_name, cc_spec->name.str, fk_info->name);
6692 6 return true;
6693 }
6694 }
6695 }
6696
6697
1/2
✓ Branch 0 taken 613260 times.
✗ Branch 1 not taken.
613260 referencing_fields.push_back(find);
6698
6699 /*
6700 Unlike for referenced columns, for referencing columns it doesn't matter
6701 which version of column name (i.e. coming from FOREIGN KEY clause or
6702 coming from table definition, they can differ in case) is stored in
6703 FOREIGN_KEY structure. Information about referencing columns is stored
6704 as their IDs in the data dictionary and as pointer to dd::Column object
6705 in in-memory representation.
6706 */
6707 613260 fk_info->key_part[column_nr].str = col->get_field_name();
6708 613260 fk_info->key_part[column_nr].length = std::strlen(col->get_field_name());
6709
6710 /*
6711 Save version of referenced column name coming from FOREIGN KEY clause.
6712 Later we will replace it with version of name coming from parent table
6713 definition if possible (these versions can differ in case).
6714 */
6715
1/2
✓ Branch 0 taken 613260 times.
✗ Branch 1 not taken.
613260 const Key_part_spec *fk_col = fk_key->ref_columns[column_nr];
6716 613260 fk_info->fk_key_part[column_nr].str = fk_col->get_field_name();
6717 613260 fk_info->fk_key_part[column_nr].length =
6718 613260 std::strlen(fk_col->get_field_name());
6719 }
6720
6721
1/2
✓ Branch 0 taken 612802 times.
✗ Branch 1 not taken.
612802 if (find_parent_key) {
6722 /*
6723 Check if we are trying to add foreign key to partitioned table
6724 and table's storage engine doesn't support foreign keys over
6725 partitioned tables.
6726 */
6727
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 612799 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 612799 times.
612805 if (is_partitioned &&
6728
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 (!create_info->db_type->partition_flags ||
6729
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 create_info->db_type->partition_flags() & HA_CANNOT_PARTITION_FK)) {
6730
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_FOREIGN_KEY_ON_PARTITIONED, MYF(0));
6731 3 return true;
6732 }
6733
6734
1/2
✓ Branch 0 taken 612799 times.
✗ Branch 1 not taken.
612799 const KEY *supporting_key = find_fk_supporting_key(
6735 create_info->db_type, alter_info, key_info_buffer, key_count, fk_info);
6736
6737
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 612798 times.
612799 if (supporting_key == nullptr) {
6738 /*
6739 Since we always add generated supporting key when adding new
6740 foreign key the failure to find key above is likely to mean
6741 that generated key was auto-converted to spatial key or it is
6742 some other corner case.
6743 */
6744
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_FK_NO_INDEX_CHILD, MYF(0), fk_info->name, table_name);
6745 1 return true;
6746 }
6747
6748
5/6
✓ Branch 0 taken 612798 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 612783 times.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 12011 times.
✓ Branch 5 taken 600787 times.
1225581 if (my_strcasecmp(table_alias_charset, fk_info->ref_db.str, db) == 0 &&
6749
3/4
✓ Branch 0 taken 612783 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12011 times.
✓ Branch 3 taken 600772 times.
612783 my_strcasecmp(table_alias_charset, fk_info->ref_table.str,
6750 table_name) == 0) {
6751 // FK which references the same table on which it is defined.
6752
2/2
✓ Branch 0 taken 12011 times.
✓ Branch 1 taken 12011 times.
24022 for (uint i = 0; i < fk_info->key_parts; i++) {
6753
1/2
✓ Branch 0 taken 12011 times.
✗ Branch 1 not taken.
12011 List_iterator_fast<Create_field> field_it(alter_info->create_list);
6754 const Create_field *field;
6755
6756 // Check that referenced column exists and is non-virtual.
6757
1/2
✓ Branch 0 taken 12012 times.
✗ Branch 1 not taken.
12012 while ((field = field_it++)) {
6758
1/2
✓ Branch 0 taken 12012 times.
✗ Branch 1 not taken.
12012 if (my_strcasecmp(system_charset_info, field->field_name,
6759
2/2
✓ Branch 0 taken 12011 times.
✓ Branch 1 taken 1 times.
12012 fk_info->fk_key_part[i].str) == 0)
6760 12011 break;
6761 }
6762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12011 times.
12011 if (field == nullptr) {
6763 my_error(ER_FK_NO_COLUMN_PARENT, MYF(0), fk_info->fk_key_part[i].str,
6764 fk_info->name, fk_info->ref_table.str);
6765 return true;
6766 }
6767
6768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12011 times.
12011 if (field->is_virtual_gcol()) {
6769 my_error(ER_FK_CANNOT_USE_VIRTUAL_COLUMN, MYF(0), fk_info->name,
6770 fk_info->fk_key_part[i].str);
6771 return true;
6772 }
6773
6774 // Check that types of referencing and referenced columns are
6775 // compatible.
6776
1/2
✓ Branch 0 taken 12011 times.
✗ Branch 1 not taken.
12011 if (create_info->db_type->check_fk_column_compat) {
6777 Ha_fk_column_type child_column_type, parent_column_type;
6778
6779
2/4
✓ Branch 0 taken 12011 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12011 times.
✗ Branch 3 not taken.
12011 fill_ha_fk_column_type(&child_column_type, referencing_fields[i]);
6780
1/2
✓ Branch 0 taken 12011 times.
✗ Branch 1 not taken.
12011 fill_ha_fk_column_type(&parent_column_type, field);
6781
6782
2/4
✓ Branch 0 taken 12011 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12011 times.
12011 if (!create_info->db_type->check_fk_column_compat(
6783 &child_column_type, &parent_column_type, true)) {
6784 my_error(ER_FK_INCOMPATIBLE_COLUMNS, MYF(0),
6785 fk_info->key_part[i].str, fk_info->fk_key_part[i].str,
6786 fk_info->name);
6787 return true;
6788 }
6789 }
6790
6791 /*
6792 Be compatible with 5.7. Use version of referenced column name
6793 coming from parent table definition and not the one that was
6794 used in FOREIGN KEY clause.
6795 */
6796 12011 fk_info->fk_key_part[i].str = field->field_name;
6797 12011 fk_info->fk_key_part[i].length = std::strlen(field->field_name);
6798 }
6799
6800
3/4
✓ Branch 0 taken 12011 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 12010 times.
12011 if (prepare_self_ref_fk_parent_key(create_info->db_type, alter_info,
6801 key_info_buffer, key_count,
6802 supporting_key, nullptr, fk_info))
6803 1 return true;
6804 } else {
6805 /*
6806 FK which references other table than one on which it is defined.
6807
6808 Check that table exists and its storage engine as the first step.
6809 */
6810 600787 const dd::Table *parent_table_def = nullptr;
6811
6812
4/8
✓ Branch 0 taken 600787 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 600787 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 600787 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 600787 times.
600787 if (thd->dd_client()->acquire(fk_info->ref_db.str, fk_info->ref_table.str,
6813 &parent_table_def))
6814 26 return true;
6815
6816 600787 handlerton *parent_hton = nullptr;
6817
3/4
✓ Branch 0 taken 325245 times.
✓ Branch 1 taken 275542 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 600787 times.
926032 if (parent_table_def != nullptr &&
6818
2/4
✓ Branch 0 taken 325245 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 325245 times.
325245 dd::table_storage_engine(thd, parent_table_def, &parent_hton))
6819 return true;
6820
6821
4/4
✓ Branch 0 taken 325245 times.
✓ Branch 1 taken 275542 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 325240 times.
600787 if (parent_table_def == nullptr || create_info->db_type != parent_hton) {
6822
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 275541 times.
275547 if (!(thd->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS)) {
6823
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(ER_FK_CANNOT_OPEN_PARENT, MYF(0), fk_info->ref_table.str);
6824 6 return true;
6825 }
6826 /*
6827 Missing parent table is legitimate case in FOREIGN_KEY_CHECKS=0 mode.
6828
6829 FOREIGN_KEY::unique_index_name should be already set to value which
6830 corresponds to NULL value in FOREIGN_KEYS.UNIQUE_CONSTRAINT_NAME
6831 column.
6832
6833 For compatibility reasons we treat difference in parent SE in the same
6834 way as missing parent table.
6835 */
6836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 275541 times.
275541 assert(fk_info->unique_index_name == nullptr);
6837 } else {
6838 /*
6839 Check that parent table is not partitioned or storage engine
6840 supports foreign keys over partitioned tables.
6841 */
6842
3/6
✓ Branch 0 taken 325240 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 325240 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 325240 times.
325240 if (parent_table_def->partition_type() != dd::Table::PT_NONE &&
6843 (!parent_hton->partition_flags ||
6844 parent_hton->partition_flags() & HA_CANNOT_PARTITION_FK)) {
6845 my_error(ER_FOREIGN_KEY_ON_PARTITIONED, MYF(0));
6846 return true;
6847 }
6848
6849 /* Then check that referenced columns exist and are non-virtual. */
6850
2/2
✓ Branch 0 taken 325696 times.
✓ Branch 1 taken 325232 times.
650928 for (uint i = 0; i < fk_info->key_parts; i++) {
6851 325696 const char *ref_column_name = fk_info->fk_key_part[i].str;
6852
6853 326249 auto same_column_name = [ref_column_name](const dd::Column *c) {
6854 326249 return my_strcasecmp(system_charset_info, c->name().c_str(),
6855 326249 ref_column_name) == 0;
6856 325696 };
6857
6858 auto ref_column =
6859
3/6
✓ Branch 0 taken 325696 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 325696 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 325696 times.
✗ Branch 5 not taken.
325696 std::find_if(parent_table_def->columns().begin(),
6860
2/4
✓ Branch 0 taken 325696 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 325696 times.
✗ Branch 3 not taken.
325696 parent_table_def->columns().end(), same_column_name);
6861
6862
3/6
✓ Branch 0 taken 325696 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 325696 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 325696 times.
325696 if (ref_column == parent_table_def->columns().end()) {
6863 my_error(ER_FK_NO_COLUMN_PARENT, MYF(0), ref_column_name,
6864 fk_info->name, fk_info->ref_table.str);
6865 8 return true;
6866 }
6867
6868
4/6
✓ Branch 0 taken 325696 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 325696 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 325694 times.
325696 if ((*ref_column)->is_virtual()) {
6869
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_FK_CANNOT_USE_VIRTUAL_COLUMN, MYF(0), fk_info->name,
6870 ref_column_name);
6871 2 return true;
6872 }
6873
6874 // Check that types of referencing and referenced columns are
6875 // compatible.
6876
1/2
✓ Branch 0 taken 325694 times.
✗ Branch 1 not taken.
325694 if (create_info->db_type->check_fk_column_compat) {
6877 Ha_fk_column_type child_column_type, parent_column_type;
6878
6879
2/4
✓ Branch 0 taken 325694 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 325694 times.
✗ Branch 3 not taken.
325694 fill_ha_fk_column_type(&child_column_type, referencing_fields[i]);
6880
3/6
✓ Branch 0 taken 325694 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 325694 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 325694 times.
325694 if (fill_ha_fk_column_type(&parent_column_type, *ref_column))
6881 6 return true;
6882
6883
3/4
✓ Branch 0 taken 325694 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 325688 times.
325694 if (!create_info->db_type->check_fk_column_compat(
6884 &child_column_type, &parent_column_type, true)) {
6885 6 my_error(ER_FK_INCOMPATIBLE_COLUMNS, MYF(0),
6886
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 fk_info->key_part[i].str, ref_column_name,
6887 fk_info->name);
6888 6 return true;
6889 }
6890 }
6891
6892 /*
6893 Be compatible with 5.7. Use version of referenced column name
6894 coming from parent table definition and not the one that was
6895 used in FOREIGN KEY clause.
6896 */
6897
2/4
✓ Branch 0 taken 325688 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 325688 times.
✗ Branch 3 not taken.
325688 fk_info->fk_key_part[i].str = (*ref_column)->name().c_str();
6898
2/4
✓ Branch 0 taken 325688 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 325688 times.
✗ Branch 3 not taken.
325688 fk_info->fk_key_part[i].length = (*ref_column)->name().length();
6899 }
6900
6901
3/4
✓ Branch 0 taken 325232 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 325220 times.
325232 if (prepare_fk_parent_key(create_info->db_type, parent_table_def,
6902 fk_info))
6903 12 return true;
6904 }
6905 }
6906 } else {
6907 assert(fk_info->unique_index_name == nullptr);
6908 }
6909
6910 612771 return false;
6911 612874 }
6912
6913 /**
6914 Check that pre-existing self-referencing foreign key or an orphan
6915 non-self-referencing foreign key become non-orphan/adopted self-referencing
6916 foreign key as a result of table rename operation will be valid after ALTER
6917 TABLE, i.e. that table has parent index and types of child and parent
6918 columns are compatible. Also update DD.UNIQUE_CONSTRAINT_NAME accordingly.
6919
6920 @param thd Thread context..
6921 @param create_info HA_CREATE_INFO describing table.
6922 @param alter_info Alter_info structure describing
6923 table.
6924 @param key_info Array of indexes.
6925 @param key_count Number of indexes.
6926 @param supporting_key Supporting key for the foreign key.
6927 @param existing_fks_table dd::Table object for table version
6928 from which pre-existing foreign keys
6929 come from. Needed for error
6930 reporting.
6931 @param referencing_fields List of foreign key referencing fields.
6932 @param[in,out] fk FOREIGN_KEY object describing
6933 pre-existing foreign key.
6934
6935 @retval true if error (error reported), false otherwise.
6936 */
6937 1 static bool prepare_preexisting_self_ref_foreign_key(
6938 THD *thd, HA_CREATE_INFO *create_info, Alter_info *alter_info,
6939 KEY *key_info, uint key_count, const KEY *supporting_key,
6940 const dd::Table *existing_fks_table, FOREIGN_KEY *fk,
6941 const Prealloced_array<Create_field *, 1> &referencing_fields) {
6942 Create_field *sql_field;
6943
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 List_iterator<Create_field> it(alter_info->create_list);
6944
6945 // Check that types of child and parent columns are still compatible.
6946
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (create_info->db_type->check_fk_column_compat) {
6947
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (size_t j = 0; j < fk->key_parts; j++) {
6948 1 it.rewind();
6949
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 while ((sql_field = it++)) {
6950
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (my_strcasecmp(system_charset_info, fk->fk_key_part[j].str,
6951
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 sql_field->field_name) == 0)
6952 1 break;
6953 }
6954 // We already have checked that referenced column exists.
6955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(sql_field != nullptr);
6956
6957 Ha_fk_column_type child_column_type, parent_column_type;
6958
6959
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 fill_ha_fk_column_type(&child_column_type, referencing_fields[j]);
6960
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 fill_ha_fk_column_type(&parent_column_type, sql_field);
6961
6962 /*
6963 Allow charset discrepancies between child and parent columns
6964 in FOREIGN_KEY_CHECKS=0 mode. This provides a way to change
6965 charset of column which participates in a foreign key without
6966 dropping the latter.
6967 We allow such discrepancies even for foreign keys that has same
6968 table as child and parent in order to be consistent with general
6969 case, in which there is no way to change charset of both child
6970 and parent columns simultaneously.
6971
6972 We do not allow creation of same discrepancies when adding
6973 new foreign key using CREATE/ALTER TABLE or adding new parent
6974 for existing orphan foreign key using CREATE/RENAME TABLE.
6975 */
6976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!create_info->db_type->check_fk_column_compat(
6977 &child_column_type, &parent_column_type,
6978
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 !(thd->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS))) {
6979 my_error(ER_FK_INCOMPATIBLE_COLUMNS, MYF(0), fk->key_part[j].str,
6980 fk->fk_key_part[j].str, fk->name);
6981 return true;
6982 }
6983 }
6984 }
6985
6986 /*
6987 Check that foreign key still has matching parent key and adjust
6988 DD.UNIQUE_CONSTRAINT_NAME accordingly.
6989 */
6990
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (prepare_self_ref_fk_parent_key(create_info->db_type, alter_info, key_info,
6991 key_count, supporting_key,
6992 existing_fks_table, fk))
6993 return true;
6994
6995 1 return false;
6996 }
6997
6998 /**
6999 Check that pre-existing foreign key will be still valid after ALTER TABLE,
7000 i.e. that table still has supporting index and types of child and parent
7001 columns are still compatible. Also if necessary check that there is parent
7002 index and update DD.UNIQUE_CONSTRAINT_NAME accordingly.
7003
7004 @param thd Thread context..
7005 @param create_info HA_CREATE_INFO describing table.
7006 @param alter_info Alter_info structure describing
7007 ALTER TABLE.
7008 @param schema_name Table schema name.
7009 @param table_name Table name.
7010 @param key_info Array of indexes.
7011 @param key_count Number of indexes.
7012 @param existing_fks_table dd::Table object for table version
7013 from which pre-existing foreign keys
7014 come from. Needed for error
7015 reporting.
7016 @param[in,out] fk FOREIGN_KEY object describing
7017 pre-existing foreign key.
7018
7019 @retval true if error (error reported), false otherwise.
7020 */
7021 264 static bool prepare_preexisting_foreign_key(
7022 THD *thd, HA_CREATE_INFO *create_info, Alter_info *alter_info,
7023 const char *schema_name, const char *table_name, KEY *key_info,
7024 uint key_count, const dd::Table *existing_fks_table, FOREIGN_KEY *fk) {
7025 Create_field *sql_field;
7026
1/2
✓ Branch 0 taken 264 times.
✗ Branch 1 not taken.
264 List_iterator<Create_field> it(alter_info->create_list);
7027 264 Prealloced_array<Create_field *, 1> referencing_fields(PSI_INSTRUMENT_ME);
7028
7029
2/2
✓ Branch 0 taken 297 times.
✓ Branch 1 taken 255 times.
552 for (size_t j = 0; j < fk->key_parts; j++) {
7030 297 it.rewind();
7031
1/2
✓ Branch 0 taken 700 times.
✗ Branch 1 not taken.
700 while ((sql_field = it++)) {
7032
1/2
✓ Branch 0 taken 700 times.
✗ Branch 1 not taken.
700 if (my_strcasecmp(system_charset_info, fk->key_part[j].str,
7033
2/2
✓ Branch 0 taken 297 times.
✓ Branch 1 taken 403 times.
700 sql_field->field_name) == 0)
7034 297 break;
7035 }
7036 // We already have checked that referencing column exists.
7037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 297 times.
297 assert(sql_field != nullptr);
7038 // Save Create_field to be used in type compatibility check later.
7039
1/2
✓ Branch 0 taken 297 times.
✗ Branch 1 not taken.
297 referencing_fields.push_back(sql_field);
7040
7041 /*
7042 Check if this foreign key has SET NULL as one of referential actions
7043 and one of its referencing columns became non-nullable.
7044
7045 We do this check here rather than in transfer_preexisting_foreign_keys()
7046 in order to avoid complicated handling of case when column becomes
7047 non-nullable implicitly because it is part of PRIMARY KEY added.
7048 */
7049
2/2
✓ Branch 0 taken 268 times.
✓ Branch 1 taken 29 times.
297 if ((fk->delete_opt == FK_OPTION_SET_NULL ||
7050
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 263 times.
268 fk->update_opt == FK_OPTION_SET_NULL) &&
7051
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 28 times.
34 (sql_field->flags & NOT_NULL_FLAG)) {
7052
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(ER_FK_COLUMN_NOT_NULL, MYF(0), fk->key_part[j].str, fk->name);
7053 6 return true;
7054 }
7055
7056 /*
7057 Check constraints evaluation is done before writing row to the storage
7058 engine but foreign key referential actions SET NULL, UPDATE CASCADE and
7059 SET DEFAULT are executed by the engine. Check constraints can not be
7060 evaluated for the these foreign key referential actions, so we prohibit
7061 them.
7062 */
7063
2/2
✓ Branch 0 taken 267 times.
✓ Branch 1 taken 24 times.
291 if (fk->delete_opt == FK_OPTION_SET_NULL ||
7064
1/2
✓ Branch 0 taken 267 times.
✗ Branch 1 not taken.
267 fk->delete_opt == FK_OPTION_DEFAULT ||
7065
2/2
✓ Branch 0 taken 263 times.
✓ Branch 1 taken 4 times.
267 fk->update_opt == FK_OPTION_SET_NULL ||
7066
1/2
✓ Branch 0 taken 263 times.
✗ Branch 1 not taken.
263 fk->update_opt == FK_OPTION_DEFAULT ||
7067
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 177 times.
263 fk->update_opt == FK_OPTION_CASCADE) {
7068
3/4
✓ Branch 0 taken 114 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 111 times.
117 for (auto &cc_spec : alter_info->check_constraint_spec_list) {
7069
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
6 if (cc_spec->expr_refers_column(sql_field->field_name)) {
7070 3 my_error(ER_CHECK_CONSTRAINT_CLAUSE_USING_FK_REFER_ACTION_COLUMN,
7071
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 MYF(0), sql_field->field_name, cc_spec->name.str, fk->name);
7072 3 return true;
7073 }
7074 }
7075 }
7076 }
7077
7078 // Check that we still have supporting index on child table.
7079
1/2
✓ Branch 0 taken 255 times.
✗ Branch 1 not taken.
255 const KEY *supporting_key = find_fk_supporting_key(
7080 create_info->db_type, alter_info, key_info, key_count, fk);
7081
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 241 times.
255 if (supporting_key == nullptr) {
7082 /*
7083 If there is no supporting index, it must have been dropped by
7084 this ALTER TABLE. Find old foreign key definition and supporting
7085 index which matched it in old table definition in order to report
7086 nice error.
7087 */
7088 34 auto same_name = [fk](const dd::Foreign_key *el) {
7089 17 return my_strcasecmp(system_charset_info, fk->name, el->name().c_str()) ==
7090 17 0;
7091 14 };
7092 auto old_fk =
7093
3/6
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
14 std::find_if(existing_fks_table->foreign_keys().begin(),
7094
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 existing_fks_table->foreign_keys().end(), same_name);
7095
3/6
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
14 assert(old_fk != existing_fks_table->foreign_keys().end());
7096
7097 28 const dd::Index *old_key = find_fk_supporting_key(
7098
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 create_info->db_type, existing_fks_table, *old_fk);
7099
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
28 my_error(ER_DROP_INDEX_FK, MYF(0),
7100
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 old_key ? old_key->name().c_str() : "<unknown key name>");
7101 14 return true;
7102 }
7103
7104
5/6
✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 237 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 240 times.
478 if (my_strcasecmp(table_alias_charset, fk->ref_db.str, schema_name) == 0 &&
7105
3/4
✓ Branch 0 taken 237 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 236 times.
237 my_strcasecmp(table_alias_charset, fk->ref_table.str, table_name) == 0) {
7106 // Pre-existing foreign key which has same table as parent and child.
7107
7108 // TODO: Run this check only in cases when column type is really changed in
7109 // order to avoid unnecessary work.
7110
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (prepare_preexisting_self_ref_foreign_key(
7111 thd, create_info, alter_info, key_info, key_count, supporting_key,
7112 existing_fks_table, fk, referencing_fields))
7113 return true;
7114 481 } else if (alter_info->new_table_name.str != nullptr &&
7115
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 my_strcasecmp(table_alias_charset, fk->ref_db.str,
7116
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 239 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 240 times.
241 alter_info->new_db_name.str) == 0 &&
7117
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 my_strcasecmp(table_alias_charset, fk->ref_table.str,
7118 alter_info->new_table_name.str) == 0) {
7119 /*
7120 Pre-existing orphan non-self-referencing foreign key become
7121 non-orphan/adopted self-referencing foreign key as a result of table
7122 rename operation.
7123 */
7124 if (prepare_preexisting_self_ref_foreign_key(
7125 thd, create_info, alter_info, key_info, key_count, supporting_key,
7126 nullptr, fk, referencing_fields))
7127 return true;
7128 } else {
7129 /*
7130 Pre-existing foreign key with different tables as child and parent.
7131
7132 There is no need to update DD.UNIQUE_CONSTRAINT_NAME.
7133
7134 Parent table definition is needed to check column types compatibility.
7135
7136 Skip check if parent table doesn't exist or uses wrong engine.
7137 */
7138
1/2
✓ Branch 0 taken 240 times.
✗ Branch 1 not taken.
240 if (create_info->db_type->check_fk_column_compat) {
7139 240 const dd::Table *parent_table_def = nullptr;
7140
4/8
✓ Branch 0 taken 240 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 240 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 240 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 240 times.
240 if (thd->dd_client()->acquire(fk->ref_db.str, fk->ref_table.str,
7141 &parent_table_def))
7142 return true;
7143
7144 240 handlerton *parent_hton = nullptr;
7145
3/4
✓ Branch 0 taken 236 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 240 times.
476 if (parent_table_def != nullptr &&
7146
2/4
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 236 times.
236 dd::table_storage_engine(thd, parent_table_def, &parent_hton))
7147 return true;
7148
7149
3/4
✓ Branch 0 taken 236 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 236 times.
✗ Branch 3 not taken.
240 if (parent_table_def != nullptr && create_info->db_type == parent_hton) {
7150
2/2
✓ Branch 0 taken 269 times.
✓ Branch 1 taken 236 times.
505 for (size_t j = 0; j < fk->key_parts; j++) {
7151 269 const char *ref_column_name = fk->fk_key_part[j].str;
7152
7153 338 auto same_column_name = [ref_column_name](const dd::Column *c) {
7154 338 return my_strcasecmp(system_charset_info, c->name().c_str(),
7155 338 ref_column_name) == 0;
7156 269 };
7157
7158 auto ref_column =
7159
3/6
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 269 times.
✗ Branch 5 not taken.
269 std::find_if(parent_table_def->columns().begin(),
7160
2/4
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
269 parent_table_def->columns().end(), same_column_name);
7161
3/6
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 269 times.
269 assert(ref_column != parent_table_def->columns().end());
7162
7163 Ha_fk_column_type child_column_type, parent_column_type;
7164
7165
2/4
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
269 fill_ha_fk_column_type(&child_column_type, referencing_fields[j]);
7166
3/6
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 269 times.
269 if (fill_ha_fk_column_type(&parent_column_type, *ref_column))
7167 return true;
7168
7169 /*
7170 See comment in prepare_preexisting_self_ref_foreign_key() about
7171 allowing charset discrepancies between child and parent columns in
7172 FOREIGN_KEY_CHECKS=0 mode.
7173 */
7174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 269 times.
269 if (!create_info->db_type->check_fk_column_compat(
7175 &child_column_type, &parent_column_type,
7176
1/2
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
269 !(thd->variables.option_bits &
7177 OPTION_NO_FOREIGN_KEY_CHECKS))) {
7178 my_error(ER_FK_INCOMPATIBLE_COLUMNS, MYF(0), fk->key_part[j].str,
7179 ref_column_name, fk->name);
7180 return true;
7181 }
7182 }
7183 }
7184 }
7185 }
7186 241 return false;
7187 264 }
7188
7189 1466549 static bool prepare_key(
7190 THD *thd, const char *error_schema_name, const char *error_table_name,
7191 HA_CREATE_INFO *create_info, List<Create_field> *create_list,
7192 const Key_spec *key, KEY **key_info_buffer, KEY *key_info,
7193 KEY_PART_INFO **key_part_info, Mem_root_array<const KEY *> &keys_to_check,
7194 uint key_number, const handler *file, int *auto_increment) {
7195
1/2
✓ Branch 0 taken 1466550 times.
✗ Branch 1 not taken.
1466549 DBUG_TRACE;
7196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1466550 times.
1466550 assert(create_list);
7197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1466550 times.
1466550 assert(key_info->flags == 0); // No flags should be set yet
7198
7199 /*
7200 General checks.
7201 */
7202
7203
5/6
✓ Branch 0 taken 1466550 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1466548 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1466549 times.
1466552 if (key->columns.size() > file->max_key_parts() &&
7204
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 key->type != KEYTYPE_SPATIAL) {
7205
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 my_error(ER_TOO_MANY_KEY_PARTS, MYF(0), file->max_key_parts());
7206 1 return true;
7207 }
7208
7209
3/4
✓ Branch 0 taken 1466548 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1466547 times.
1466549 if (check_string_char_length(key->name, "", NAME_CHAR_LEN,
7210 system_charset_info, true)) {
7211
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_TOO_LONG_IDENT, MYF(0), key->name.str);
7212 1 return true;
7213 }
7214
7215
6/6
✓ Branch 0 taken 139362 times.
✓ Branch 1 taken 1327185 times.
✓ Branch 2 taken 85724 times.
✓ Branch 3 taken 53638 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 1466543 times.
1552271 if (key->name.str && (key->type != KEYTYPE_PRIMARY) &&
7216
3/4
✓ Branch 0 taken 85724 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 85720 times.
85724 !my_strcasecmp(system_charset_info, key->name.str, primary_key_name)) {
7217
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
7218 4 return true;
7219 }
7220
7221 /* Create the key name based on the first column (if not given) */
7222
2/2
✓ Branch 0 taken 500995 times.
✓ Branch 1 taken 965548 times.
1466543 if (key->type == KEYTYPE_PRIMARY)
7223 500995 key_info->name = primary_key_name;
7224
2/2
✓ Branch 0 taken 85720 times.
✓ Branch 1 taken 879828 times.
965548 else if (key->name.str)
7225 85720 key_info->name = key->name.str;
7226 else {
7227
1/2
✓ Branch 0 taken 879828 times.
✗ Branch 1 not taken.
879828 const Key_part_spec *first_col = key->columns[0];
7228
1/2
✓ Branch 0 taken 879828 times.
✗ Branch 1 not taken.
879828 List_iterator<Create_field> it(*create_list);
7229 Create_field *sql_field;
7230
4/4
✓ Branch 0 taken 6534705 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 5654895 times.
✓ Branch 3 taken 879828 times.
7414551 while ((sql_field = it++) &&
7231
3/4
✓ Branch 0 taken 6534705 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5654895 times.
✓ Branch 3 taken 879810 times.
6534705 my_strcasecmp(system_charset_info, first_col->get_field_name(),
7232 sql_field->field_name))
7233 ;
7234
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 879810 times.
879828 if (!sql_field) {
7235
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0),
7236 first_col->get_field_name());
7237 18 return true;
7238 }
7239 1759620 key_info->name =
7240
1/2
✓ Branch 0 taken 879810 times.
✗ Branch 1 not taken.
879810 make_unique_key_name(sql_field->field_name, *key_info_buffer, key_info);
7241 }
7242
4/4
✓ Branch 0 taken 965530 times.
✓ Branch 1 taken 500995 times.
✓ Branch 2 taken 989 times.
✓ Branch 3 taken 1465536 times.
2432055 if (key->type != KEYTYPE_PRIMARY &&
7243
3/4
✓ Branch 0 taken 965530 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 989 times.
✓ Branch 3 taken 964541 times.
965530 check_if_keyname_exists(key_info->name, *key_info_buffer, key_info)) {
7244
1/2
✓ Branch 0 taken 989 times.
✗ Branch 1 not taken.
989 my_error(ER_DUP_KEYNAME, MYF(0), key_info->name);
7245 989 return true;
7246 }
7247
7248
6/8
✓ Branch 0 taken 1465536 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1465537 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1465535 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1465535 times.
1465536 if (!key_info->name || check_column_name(key_info->name)) {
7249
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
7250 2 return true;
7251 }
7252
7253 1465535 key_info->comment.length = key->key_create_info.comment.length;
7254 1465535 key_info->comment.str = key->key_create_info.comment.str;
7255
7256 // Validate index comment string
7257 1465535 std::string invalid_sub_str;
7258
3/4
✓ Branch 0 taken 1465534 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1465533 times.
1465535 if (is_invalid_string({key_info->comment.str, key_info->comment.length},
7259 system_charset_info, invalid_sub_str)) {
7260
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 my_error(ER_COMMENT_CONTAINS_INVALID_STRING, MYF(0), "index",
7261
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 (std::string(error_schema_name) + "." +
7262
4/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
4 std::string(error_table_name) + "." + std::string(key->name.str))
7263 .c_str(),
7264 system_charset_info->csname, invalid_sub_str.c_str());
7265 1 return true;
7266 }
7267
7268
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1465528 times.
1465534 if (validate_comment_length(thd, key_info->comment.str,
7269
1/2
✓ Branch 0 taken 1465534 times.
✗ Branch 1 not taken.
1465533 &key_info->comment.length, INDEX_COMMENT_MAXLEN,
7270 ER_TOO_LONG_INDEX_COMMENT, key_info->name))
7271 6 return true;
7272
2/2
✓ Branch 0 taken 1622 times.
✓ Branch 1 taken 1463906 times.
1465528 if (key_info->comment.length > 0) key_info->flags |= HA_USES_COMMENT;
7273
7274 1465528 key_info->engine_attribute = key->key_create_info.m_engine_attribute;
7275
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1465513 times.
1465528 if (key_info->engine_attribute.length > 0)
7276 15 key_info->flags |= HA_INDEX_USES_ENGINE_ATTRIBUTE;
7277 1465528 key_info->secondary_engine_attribute =
7278 key->key_create_info.m_secondary_engine_attribute;
7279
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 1465507 times.
1465528 if (key_info->secondary_engine_attribute.length > 0)
7280 21 key_info->flags |= HA_INDEX_USES_SECONDARY_ENGINE_ATTRIBUTE;
7281 #ifndef NDEBUG
7282 1465528 decltype(key_info->flags) flags_before_switch = key_info->flags;
7283 #endif /* NDEBUG */
7284
6/7
✓ Branch 0 taken 510248 times.
✓ Branch 1 taken 2444 times.
✓ Branch 2 taken 1313 times.
✓ Branch 3 taken 951503 times.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
1465528 switch (static_cast<int>(key->type)) {
7285 510248 case KEYTYPE_MULTIPLE:
7286 510248 break;
7287 2444 case KEYTYPE_FULLTEXT:
7288
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2440 times.
2444 if (!(file->ha_table_flags() & HA_CAN_FULLTEXT)) {
7289
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0));
7290 4 return true;
7291 }
7292 2440 key_info->flags |= HA_FULLTEXT;
7293
2/2
✓ Branch 0 taken 1169 times.
✓ Branch 1 taken 1271 times.
2440 if (key->key_create_info.parser_name.str) {
7294 1169 key_info->parser_name = key->key_create_info.parser_name;
7295 1169 key_info->flags |= HA_USES_PARSER;
7296 } else
7297 1271 key_info->parser_name = NULL_CSTR;
7298 2440 break;
7299 1313 case KEYTYPE_SPATIAL:
7300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1313 times.
1313 if (!(file->ha_table_flags() & HA_CAN_RTREEKEYS)) {
7301 my_error(ER_TABLE_CANT_HANDLE_SPKEYS, MYF(0));
7302 return true;
7303 }
7304
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1309 times.
1313 if (key->columns.size() != 1) {
7305
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_TOO_MANY_KEY_PARTS, MYF(0), 1);
7306 4 return true;
7307 }
7308 1309 key_info->flags |= HA_SPATIAL;
7309 1309 break;
7310 951503 case KEYTYPE_PRIMARY:
7311 case KEYTYPE_UNIQUE:
7312 951503 key_info->flags |= HA_NOSAME;
7313 951503 break;
7314 19 case KEYTYPE_CLUSTERING | KEYTYPE_UNIQUE:
7315 case KEYTYPE_CLUSTERING | KEYTYPE_MULTIPLE:
7316
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (thd->work_part_info) {
7317 1 partition_info *part_info = thd->work_part_info;
7318
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 List_iterator<partition_element> part_it(part_info->partitions);
7319 partition_element *part_elem;
7320
7321
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 while ((part_elem = part_it++)) {
7322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (part_elem->subpartitions.elements) {
7323 List_iterator<partition_element> sub_it(part_elem->subpartitions);
7324 partition_element *subpart_elem;
7325 while ((subpart_elem = sub_it++)) {
7326 if (unlikely(!ha_check_storage_engine_flag(
7327 subpart_elem->engine_type,
7328 HTON_SUPPORTS_CLUSTERED_KEYS))) {
7329 my_error(
7330 ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
7331 ha_resolve_storage_engine_name(subpart_elem->engine_type),
7332 "CLUSTERING");
7333 return true;
7334 }
7335 }
7336
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 } else if (unlikely(!ha_check_storage_engine_flag(
7337 1 part_elem->engine_type,
7338 HTON_SUPPORTS_CLUSTERED_KEYS))) {
7339
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
7340
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ha_resolve_storage_engine_name(part_elem->engine_type),
7341 "CLUSTERING");
7342 1 return true;
7343 }
7344 }
7345
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 } else if (unlikely(!ha_check_storage_engine_flag(
7346 18 file->ht, HTON_SUPPORTS_CLUSTERED_KEYS))) {
7347
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
7348
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 ha_resolve_storage_engine_name(file->ht), "CLUSTERING");
7349 18 return true;
7350 }
7351 if (key->type & KEYTYPE_UNIQUE)
7352 key_info->flags = HA_NOSAME;
7353 else
7354 key_info->flags = 0;
7355 key_info->flags |= HA_CLUSTERING;
7356 break;
7357 case KEYTYPE_CLUSTERING:
7358 assert(0);
7359 1 default:
7360 1 assert(false);
7361 return true;
7362 }
7363 // Verify that no bits set before switch have been cleared.
7364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1465500 times.
1465500 assert((key_info->flags & flags_before_switch) == flags_before_switch);
7365
2/2
✓ Branch 0 taken 1446 times.
✓ Branch 1 taken 1464054 times.
1465500 if (key->generated) key_info->flags |= HA_GENERATED_KEY;
7366
7367 1465500 key_info->algorithm = key->key_create_info.algorithm;
7368 1465500 key_info->user_defined_key_parts = key->columns.size();
7369 1465501 key_info->actual_key_parts = key_info->user_defined_key_parts;
7370 1465501 key_info->key_part = *key_part_info;
7371 1465501 key_info->usable_key_parts = key_number;
7372 1465501 key_info->is_algorithm_explicit = false;
7373 1465501 key_info->is_visible = key->key_create_info.is_visible;
7374
7375 /*
7376 Make SPATIAL to be RTREE by default
7377 SPATIAL only on BLOB or at least BINARY, this
7378 actually should be replaced by special GEOM type
7379 in near future when new frm file is ready
7380 checking for proper key parts number:
7381 */
7382
7383
2/2
✓ Branch 0 taken 1309 times.
✓ Branch 1 taken 1464192 times.
1465501 if (key_info->flags & HA_SPATIAL) {
7384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1309 times.
1309 assert(!key->key_create_info.is_algorithm_explicit);
7385 1309 key_info->algorithm = HA_KEY_ALG_RTREE;
7386
2/2
✓ Branch 0 taken 2440 times.
✓ Branch 1 taken 1461752 times.
1464192 } else if (key_info->flags & HA_FULLTEXT) {
7387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2440 times.
2440 assert(!key->key_create_info.is_algorithm_explicit);
7388 2440 key_info->algorithm = HA_KEY_ALG_FULLTEXT;
7389 } else {
7390
2/2
✓ Branch 0 taken 60393 times.
✓ Branch 1 taken 1401359 times.
1461752 if (key->key_create_info.is_algorithm_explicit) {
7391
2/2
✓ Branch 0 taken 60384 times.
✓ Branch 1 taken 9 times.
60393 if (key->key_create_info.algorithm != HA_KEY_ALG_RTREE) {
7392 /*
7393 If key algorithm was specified explicitly check if it is
7394 supported by SE.
7395 */
7396
2/2
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 60013 times.
60384 if (file->is_index_algorithm_supported(
7397
1/2
✓ Branch 0 taken 60384 times.
✗ Branch 1 not taken.
60384 key->key_create_info.algorithm)) {
7398 371 key_info->is_algorithm_explicit = true;
7399 371 key_info->algorithm = key->key_create_info.algorithm;
7400 } else {
7401 /*
7402 If explicit algorithm is not supported by SE, replace it with
7403 default one. Don't mark key algorithm as explicitly specified
7404 in this case.
7405 */
7406
1/2
✓ Branch 0 taken 60013 times.
✗ Branch 1 not taken.
60013 key_info->algorithm = file->get_default_index_algorithm();
7407
7408
2/4
✓ Branch 0 taken 60013 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 60014 times.
✗ Branch 3 not taken.
60013 push_warning_printf(
7409 thd, Sql_condition::SL_NOTE, ER_UNSUPPORTED_INDEX_ALGORITHM,
7410 ER_THD(thd, ER_UNSUPPORTED_INDEX_ALGORITHM),
7411
2/2
✓ Branch 0 taken 59998 times.
✓ Branch 1 taken 15 times.
60013 ((key->key_create_info.algorithm == HA_KEY_ALG_HASH) ? "HASH"
7412 : "BTREE"));
7413 }
7414 }
7415 } else {
7416 /*
7417 If key algorithm was not explicitly specified used default one for
7418 this SE. Interesting side-effect of this is that ALTER TABLE will
7419 cause index rebuild if SE default changes.
7420 Assert that caller doesn't use any non-default algorithm in this
7421 case as such setting is ignored anyway.
7422 */
7423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1401359 times.
1401359 assert(key->key_create_info.algorithm == HA_KEY_ALG_SE_SPECIFIC);
7424
1/2
✓ Branch 0 taken 1401358 times.
✗ Branch 1 not taken.
1401359 key_info->algorithm = file->get_default_index_algorithm();
7425 }
7426 }
7427
7428 /*
7429 Take block size from key part or table part
7430 TODO: Add warning if block size changes. We can't do it here, as
7431 this may depend on the size of the key
7432 */
7433 1465220 key_info->block_size =
7434
2/2
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 1465220 times.
1465501 (key->key_create_info.block_size ? key->key_create_info.block_size
7435 : create_info->key_block_size);
7436
7437
2/2
✓ Branch 0 taken 1121 times.
✓ Branch 1 taken 1464380 times.
1465501 if (key_info->block_size) key_info->flags |= HA_USES_BLOCK_SIZE;
7438
7439 1465501 const CHARSET_INFO *ft_key_charset = nullptr; // for FULLTEXT
7440 1465501 key_info->key_length = 0;
7441
2/2
✓ Branch 0 taken 2332319 times.
✓ Branch 1 taken 1465210 times.
3797531 for (size_t column_nr = 0; column_nr < key->columns.size();
7442 2332030 column_nr++, (*key_part_info)++) {
7443
2/2
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 2332030 times.
2332320 if (prepare_key_column(thd, create_info, create_list, key,
7444
2/4
✓ Branch 0 taken 2332320 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2332320 times.
✗ Branch 3 not taken.
2332319 key->columns[column_nr], column_nr, key_info,
7445 *key_part_info, file, auto_increment,
7446 &ft_key_charset))
7447 290 return true;
7448 }
7449 1465210 key_info->actual_flags = key_info->flags;
7450
7451
5/6
✓ Branch 0 taken 1465211 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 338 times.
✓ Branch 3 taken 1464873 times.
✓ Branch 4 taken 323 times.
✓ Branch 5 taken 1464888 times.
1465548 if (key_info->key_length > file->max_key_length() &&
7452
2/2
✓ Branch 0 taken 323 times.
✓ Branch 1 taken 15 times.
338 key->type != KEYTYPE_FULLTEXT) {
7453
2/4
✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 323 times.
✗ Branch 3 not taken.
323 my_error(ER_TOO_LONG_KEY, MYF(0), file->max_key_length());
7454
3/4
✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 301 times.
323 if (thd->is_error()) // May be silenced - see Bug#20629014
7455 22 return true;
7456 }
7457
7458 /*
7459 We only check for duplicate indexes if it is requested and the key is
7460 not auto-generated and non-PRIMARY.
7461
7462 Check is requested if the key was explicitly created or altered
7463 (Index is altered/column associated with it is dropped) by the user
7464 (unless it's a foreign key).
7465
7466 The fact that we have only one PRIMARY key for the table is checked
7467 elsewhere.
7468
7469 At this point we simply add qualifying keys to the list, so we can
7470 perform check later when we properly construct KEY objects for all
7471 keys.
7472 */
7473
4/4
✓ Branch 0 taken 1380532 times.
✓ Branch 1 taken 84657 times.
✓ Branch 2 taken 1379314 times.
✓ Branch 3 taken 1218 times.
1465189 if (key->check_for_duplicate_indexes && !key->generated &&
7474
2/2
✓ Branch 0 taken 929339 times.
✓ Branch 1 taken 449975 times.
1379314 key->type != KEYTYPE_PRIMARY) {
7475
2/4
✓ Branch 0 taken 929339 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 929339 times.
929339 if (keys_to_check.push_back(key_info)) return true;
7476 }
7477 1465189 return false;
7478 1466550 }
7479
7480 /**
7481 Primary/unique key check. Checks that:
7482
7483 - If the storage engine requires it, that there is an index that is
7484 candidate for promotion.
7485
7486 - If such a promotion occurs, checks that the candidate index is not
7487 declared invisible.
7488
7489 @param file The storage engine handler.
7490 @param key_info_buffer All indexes in the table.
7491 @param key_count Number of indexes.
7492
7493 @retval false OK.
7494 @retval true An error occurred and my_error() was called.
7495 */
7496
7497 247401 static bool check_promoted_index(const handler *file,
7498 const KEY *key_info_buffer, uint key_count) {
7499 247401 bool has_unique_key = false;
7500 247401 const KEY *end = key_info_buffer + key_count;
7501
4/4
✓ Branch 0 taken 114928 times.
✓ Branch 1 taken 223407 times.
✓ Branch 2 taken 90935 times.
✓ Branch 3 taken 23993 times.
338335 for (const KEY *k = key_info_buffer; k < end && !has_unique_key; ++k)
7502
4/4
✓ Branch 0 taken 45929 times.
✓ Branch 1 taken 45006 times.
✓ Branch 2 taken 39169 times.
✓ Branch 3 taken 6760 times.
90935 if (!(k->flags & HA_NULL_PART_KEY) && (k->flags & HA_NOSAME)) {
7503 39169 has_unique_key = true;
7504
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 39168 times.
39169 if (!k->is_visible) {
7505 1 my_error(ER_PK_INDEX_CANT_BE_INVISIBLE, MYF(0));
7506 1 return true;
7507 }
7508 }
7509
4/6
✓ Branch 0 taken 208245 times.
✓ Branch 1 taken 39155 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 208241 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 247396 times.
247400 if (!has_unique_key && (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY)) {
7510 my_error(ER_REQUIRES_PRIMARY_KEY, MYF(0));
7511 return true;
7512 }
7513 247396 return false;
7514 }
7515
7516 namespace {
7517 /**
7518 This class is used as an input argument to Item::walk, and takes care of
7519 replacing the field pointer in Item_field with pointers to a
7520 Create_field_wrapper. This allows us to get the metadata for a column that
7521 isn't created yet (Create_field).
7522 */
7523 class Replace_field_processor_arg {
7524 public:
7525 568 Replace_field_processor_arg(THD *thd, List<Create_field> *fields,
7526 const HA_CREATE_INFO *create_info,
7527 const char *functional_index_name)
7528 568 : m_thd(thd),
7529 568 m_fields(fields),
7530 568 m_create_info(create_info),
7531 568 m_functional_index_name(functional_index_name) {}
7532
7533 const HA_CREATE_INFO *create_info() const { return m_create_info; }
7534
7535 628 const THD *thd() const { return m_thd; }
7536
7537 631 List<Create_field> const *fields() const { return m_fields; }
7538
7539 const char *functional_index_name() const { return m_functional_index_name; }
7540
7541 private:
7542 THD *m_thd;
7543 List<Create_field> *m_fields;
7544 const HA_CREATE_INFO *m_create_info;
7545 const char *m_functional_index_name;
7546 };
7547 } // namespace
7548
7549 631 bool Item_field::replace_field_processor(uchar *arg) {
7550 Replace_field_processor_arg *targ =
7551 631 pointer_cast<Replace_field_processor_arg *>(arg);
7552
7553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 631 times.
631 if (field_name == nullptr) {
7554 // Ideally we should be able to handle the function DEFAULT() as well,
7555 // but that seems rather difficult since it relies on having a TABLE object
7556 // available (which we obviously don't have during CREATE TABLE). So
7557 // disallow that function for now.
7558 assert(type() == Item::INSERT_VALUE_ITEM ||
7559 type() == Item::DEFAULT_VALUE_ITEM);
7560 my_error(ER_FUNCTIONAL_INDEX_FUNCTION_IS_NOT_ALLOWED, MYF(0),
7561 targ->functional_index_name());
7562 return true;
7563 }
7564
7565 631 const Create_field *create_field = nullptr;
7566
5/8
✓ Branch 0 taken 631 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 631 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1164 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1161 times.
✓ Branch 7 taken 3 times.
1164 for (const Create_field &create_field_it : *targ->fields()) {
7567
1/2
✓ Branch 0 taken 1161 times.
✗ Branch 1 not taken.
1161 if (my_strcasecmp(system_charset_info, field_name,
7568
2/2
✓ Branch 0 taken 628 times.
✓ Branch 1 taken 533 times.
1161 create_field_it.field_name) == 0) {
7569 628 create_field = &create_field_it;
7570 628 break;
7571 }
7572 }
7573
7574
2/2
✓ Branch 0 taken 628 times.
✓ Branch 1 taken 3 times.
631 if (create_field) {
7575
2/4
✓ Branch 0 taken 628 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 628 times.
✗ Branch 3 not taken.
628 field = new (targ->thd()->mem_root) Create_field_wrapper(create_field);
7576
15/16
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 295 times.
✓ Branch 9 taken 3 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 291 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
628 switch (create_field->sql_type) {
7577 1 case MYSQL_TYPE_TINY_BLOB:
7578 case MYSQL_TYPE_MEDIUM_BLOB:
7579 case MYSQL_TYPE_LONG_BLOB:
7580 case MYSQL_TYPE_BLOB: {
7581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(create_field->charset != nullptr);
7582 1 set_data_type_string(blob_length_by_type(create_field->sql_type),
7583 1 create_field->charset);
7584 1 break;
7585 }
7586 20 case MYSQL_TYPE_STRING:
7587 case MYSQL_TYPE_VARCHAR: {
7588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 assert(create_field->charset != nullptr);
7589 20 set_data_type_string(create_field->max_display_width_in_codepoints(),
7590 20 create_field->charset);
7591 20 break;
7592 }
7593 1 case MYSQL_TYPE_NEWDECIMAL: {
7594 2 uint precision = my_decimal_length_to_precision(
7595 1 create_field->max_display_width_in_codepoints(),
7596 1 create_field->decimals, create_field->is_unsigned);
7597 1 set_data_type_decimal(precision, create_field->decimals);
7598 1 break;
7599 }
7600 3 case MYSQL_TYPE_DATETIME2: {
7601 3 set_data_type_datetime(create_field->decimals);
7602 3 break;
7603 }
7604 1 case MYSQL_TYPE_TIMESTAMP2: {
7605 1 set_data_type_timestamp(create_field->decimals);
7606 1 break;
7607 }
7608 2 case MYSQL_TYPE_NEWDATE: {
7609 2 set_data_type_date();
7610 2 break;
7611 }
7612 5 case MYSQL_TYPE_TIME2: {
7613 5 set_data_type_time(create_field->decimals);
7614 5 break;
7615 }
7616 1 case MYSQL_TYPE_YEAR: {
7617 1 set_data_type_year();
7618 1 break;
7619 }
7620 295 case MYSQL_TYPE_INT24:
7621 case MYSQL_TYPE_TINY:
7622 case MYSQL_TYPE_SHORT:
7623 case MYSQL_TYPE_LONG:
7624 case MYSQL_TYPE_LONGLONG:
7625 case MYSQL_TYPE_BIT: {
7626 295 fix_char_length(create_field->max_display_width_in_codepoints());
7627 295 set_data_type(create_field->sql_type);
7628 295 collation.set_numeric();
7629 295 break;
7630 }
7631 3 case MYSQL_TYPE_DOUBLE: {
7632 3 set_data_type_double();
7633 3 decimals = create_field->decimals;
7634 3 break;
7635 }
7636 1 case MYSQL_TYPE_FLOAT: {
7637 1 set_data_type_float();
7638 1 decimals = create_field->decimals;
7639 1 break;
7640 }
7641 291 case MYSQL_TYPE_JSON: {
7642 291 set_data_type_json();
7643 291 break;
7644 }
7645 1 case MYSQL_TYPE_GEOMETRY: {
7646 1 set_data_type_geometry();
7647 1 break;
7648 }
7649 1 case MYSQL_TYPE_ENUM: {
7650 1 set_data_type(create_field->sql_type);
7651 1 collation.collation = create_field->charset;
7652 1 fix_char_length(create_field->max_display_width_in_codepoints());
7653 1 break;
7654 }
7655 2 case MYSQL_TYPE_SET: {
7656 2 set_data_type(create_field->sql_type);
7657 2 collation.collation = create_field->charset;
7658 2 fix_char_length(create_field->max_display_width_in_codepoints());
7659 2 break;
7660 }
7661 default: {
7662 assert(false); /* purecov: deadcode */
7663 }
7664 }
7665
7666 628 fixed = true;
7667 } else {
7668 // If the field could not be found, it means that we have added a reference
7669 // to a non-existing field. Report an error and return.
7670 3 my_error(ER_BAD_FIELD_ERROR, MYF(0), field_name, "functional index");
7671 3 return true;
7672 }
7673
7674
4/4
✓ Branch 0 taken 625 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 622 times.
1253 unsigned_flag = create_field->sql_type == MYSQL_TYPE_BIT ||
7675 625 field->is_flag_set(UNSIGNED_FLAG);
7676 628 set_nullable(create_field->is_nullable);
7677 628 field->field_length = max_length;
7678 628 return false;
7679 }
7680
7681 /**
7682 Check if the given key name exists in the array of keys. The lookup is
7683 case insensitive.
7684
7685 @param keys the array to check for the key name in
7686 @param key_name the key name to look for.
7687 @param key_to_ignore a pointer to the key we don't want to check against. This
7688 is used when checking for duplicate functional index names.
7689
7690 @retval true if the key name exists in the array
7691 @retval false if the key name doesn't exist in the array
7692 */
7693 175 static bool key_name_exists(const Mem_root_array<Key_spec *> &keys,
7694 const std::string &key_name,
7695 const Key_spec *key_to_ignore) {
7696
2/2
✓ Branch 0 taken 321 times.
✓ Branch 1 taken 130 times.
451 for (Key_spec *key_spec : keys) {
7697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 321 times.
321 if (key_spec == key_to_ignore) {
7698 continue;
7699 }
7700
7701
4/4
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 227 times.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 276 times.
415 if (key_spec->name.str != nullptr &&
7702
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 49 times.
94 my_strcasecmp(system_charset_info, key_name.c_str(),
7703 key_spec->name.str) == 0) {
7704 45 return true;
7705 }
7706 }
7707
7708 130 return false;
7709 }
7710
7711 /// Checks if a column with the given name exists in a list of fields.
7712 573 static bool column_name_exists(const List<Create_field> &fields,
7713 const string &column_name) {
7714
5/8
✓ Branch 0 taken 573 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 573 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2674 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2103 times.
✓ Branch 7 taken 571 times.
2674 for (const Create_field &field : fields) {
7715
1/2
✓ Branch 0 taken 2103 times.
✗ Branch 1 not taken.
2103 if (my_strcasecmp(system_charset_info, column_name.c_str(),
7716
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2101 times.
2103 field.field_name) == 0) {
7717 2 return true;
7718 }
7719 }
7720 571 return false;
7721 }
7722
7723 /**
7724 Create a name for the hidden generated column that represents the functional
7725 key part.
7726
7727 The name is a string on the form `!hidden!index_name!key_part!counter`. The
7728 counter is usually 0, but is incremented until a unique name is found, in the
7729 unlikely event that there is another column with the same name. The index_name
7730 part may be truncated to make sure the column name does not exceed the maximum
7731 column name length (NAME_CHAR_LEN).
7732
7733 @param key_name the name of the index.
7734 @param key_part_number the key part number, starting from zero.
7735 @param fields the other columns in the table
7736 @param mem_root the MEM_ROOT where the column name should be allocated.
7737
7738 @returns the name for the hidden generated column, allocated on the supplied
7739 MEM_ROOT
7740 */
7741 571 static const char *make_functional_index_column_name(
7742 std::string_view key_name, unsigned key_part_number,
7743 const List<Create_field> &fields, MEM_ROOT *mem_root) {
7744 // Loop until we have found a unique name. We'll usually find one in the first
7745 // iteration, but if there are user-defined columns using the same naming
7746 // scheme, we might need to increment the counter to avoid collisions. We're
7747 // guaranteed to find a unique name in at most fields.size() + 1 iterations.
7748 571 for (unsigned count = 0;; ++count) {
7749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 573 times.
573 assert(count <= fields.size());
7750
7751
1/2
✓ Branch 0 taken 573 times.
✗ Branch 1 not taken.
573 string name("!hidden!");
7752
1/2
✓ Branch 0 taken 573 times.
✗ Branch 1 not taken.
573 name += key_name;
7753
7754
1/2
✓ Branch 0 taken 573 times.
✗ Branch 1 not taken.
573 string suffix("!");
7755
2/4
✓ Branch 0 taken 573 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 573 times.
✗ Branch 3 not taken.
573 suffix += to_string(key_part_number);
7756
1/2
✓ Branch 0 taken 573 times.
✗ Branch 1 not taken.
573 suffix += '!';
7757
2/4
✓ Branch 0 taken 573 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 573 times.
✗ Branch 3 not taken.
573 suffix += to_string(count);
7758
7759 // If the name is so long that we hit the NAME_CHAR_LEN limit, truncate the
7760 // index name part, so that there is enough room to add the suffix with the
7761 // key part number and the counter. (If we had truncated the counter, we
7762 // could loop forever because the generated name is the same in each
7763 // iteration.)
7764
1/2
✓ Branch 0 taken 573 times.
✗ Branch 1 not taken.
573 name.resize(min(name.size(), NAME_CHAR_LEN - suffix.size()));
7765
1/2
✓ Branch 0 taken 573 times.
✗ Branch 1 not taken.
573 name.append(suffix);
7766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 573 times.
573 assert(name.size() <= NAME_CHAR_LEN);
7767
7768
3/4
✓ Branch 0 taken 573 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 571 times.
573 if (column_name_exists(fields, name)) {
7769 2 continue;
7770 }
7771
7772
1/2
✓ Branch 0 taken 571 times.
✗ Branch 1 not taken.
1142 return strmake_root(mem_root, name.data(), name.size());
7773
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 571 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 571 times.
1146 }
7774 }
7775
7776 /**
7777 Whether or not we have a replication setup, _and_ the master sorts
7778 functional index columns last in the table. Sorting said columns last was
7779 introduced in version 8.0.18, and this function helps us keep consistent
7780 behavior in a OLD->NEW replication setup.
7781
7782 @returns false if we have a replication setup, _and_ the server is on a old
7783 version that doesn't sort functional index columns last.
7784 */
7785 875 static bool is_not_slave_or_master_sorts_functional_index_columns_last(
7786 uint32_t master_version) {
7787 // From version 8.0.18, the server will sort functional index columns last in
7788 // the table.
7789
3/4
✓ Branch 0 taken 873 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 873 times.
✗ Branch 3 not taken.
875 return master_version >= 80018 && master_version != UNKNOWN_SERVER_VERSION;
7790 }
7791
7792 /**
7793 Prepares a functional index by adding a hidden indexed generated column for
7794 the key part.
7795
7796 A functional index is implemented as a hidden generated column over the
7797 expression specified in the index, and the hidden generated column is then
7798 indexed. This function adds a hidden generated column to the Create_list,
7799 and updates the key specification to point to this new column. The generated
7800 column is given a name that is a hash of the key name and the key part number.
7801
7802 @param thd The thread handler
7803 @param key_spec The index that contains the key part.-
7804 @param alter_info A structure describing the changes to be carried out. This
7805 structure will be updated with the new generated column.
7806 @param kp The specification of the key part. This contains the expression we
7807 will create a generated column for, and it will be updated to point
7808 at the newly created generated column.
7809 @param key_part_number The number of the key part.
7810 @param create_info A structure describing the table to be created
7811
7812 @returns The newly added Create_field on success, of nullptr in case of errors
7813 */
7814 586 static Create_field *add_functional_index_to_create_list(
7815 THD *thd, Key_spec *key_spec, Alter_info *alter_info, Key_part_spec *kp,
7816 uint key_part_number, HA_CREATE_INFO *create_info) {
7817 // A functional index cannot be a primary key
7818
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 580 times.
586 if (key_spec->type == KEYTYPE_PRIMARY) {
7819
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(ER_FUNCTIONAL_INDEX_PRIMARY_KEY, MYF(0));
7820 6 return nullptr;
7821 }
7822
7823 // If the key isn't given a name explicitly by the user, we must auto-generate
7824 // a name here. "Normal" indexes will be given a name in prepare_key(), but
7825 // that is too late for functional indexes since we want the hidden generated
7826 // column name to be based on the index name.
7827
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 450 times.
580 if (key_spec->name.str == nullptr) {
7828 130 std::string key_name;
7829 130 int count = 2;
7830
1/2
✓ Branch 0 taken 130 times.
✗ Branch 1 not taken.
130 key_name.assign("functional_index");
7831
3/4
✓ Branch 0 taken 175 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 130 times.
175 while (key_name_exists(alter_info->key_list, key_name, nullptr)) {
7832
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 key_name.assign("functional_index_");
7833
2/4
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
45 key_name.append(std::to_string(count++));
7834 }
7835
7836 130 key_spec->name.length = key_name.size();
7837
1/2
✓ Branch 0 taken 130 times.
✗ Branch 1 not taken.
130 key_spec->name.str = strmake_root(thd->stmt_arena->mem_root,
7838 key_name.c_str(), key_name.size());
7839 130 }
7840
7841 // First we need to resolve the expression in the functional index so that we
7842 // know the correct collation, data type, length etc...
7843 580 ulong saved_privilege = thd->want_privilege;
7844 580 thd->want_privilege = SELECT_ACL;
7845
7846 {
7847 // Create a scope guard so that we are guaranteed that the privileges are
7848 // set back to the original value.
7849 auto handler_guard = create_scope_guard(
7850
1/2
✓ Branch 0 taken 580 times.
✗ Branch 1 not taken.
580 [thd, saved_privilege]() { thd->want_privilege = saved_privilege; });
7851
7852 Functional_index_error_handler error_handler(
7853
2/4
✓ Branch 0 taken 580 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 580 times.
✗ Branch 3 not taken.
1160 {key_spec->name.str, key_spec->name.length}, thd);
7854
7855
1/2
✓ Branch 0 taken 580 times.
✗ Branch 1 not taken.
580 Item *expr = kp->get_expression();
7856
3/4
✓ Branch 0 taken 580 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 576 times.
580 if (expr->type() == Item::FIELD_ITEM) {
7857
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_FUNCTIONAL_INDEX_ON_FIELD, MYF(0));
7858 4 return nullptr;
7859 }
7860
7861
4/6
✓ Branch 0 taken 576 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 576 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 568 times.
576 if (pre_validate_value_generator_expr(
7862 kp->get_expression(), key_spec->name.str, VGS_GENERATED_COLUMN)) {
7863 8 return nullptr;
7864 }
7865
7866 Replace_field_processor_arg replace_field_argument(
7867 568 thd, &alter_info->create_list, create_info, key_spec->name.str);
7868
3/4
✓ Branch 0 taken 568 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 565 times.
568 if (expr->walk(&Item::replace_field_processor, enum_walk::PREFIX,
7869 reinterpret_cast<uchar *>(&replace_field_argument))) {
7870 3 return nullptr;
7871 }
7872
7873
3/4
✓ Branch 0 taken 565 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 562 times.
565 if (kp->resolve_expression(thd)) return nullptr;
7874
4/4
✓ Branch 0 taken 562 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 562 times.
✓ Branch 3 taken 18 times.
598 }
7875
7876
1/2
✓ Branch 0 taken 562 times.
✗ Branch 1 not taken.
562 const char *field_name = make_functional_index_column_name(
7877 {key_spec->name.str, key_spec->name.length}, key_part_number,
7878 562 alter_info->create_list, thd->stmt_arena->mem_root);
7879
7880
1/2
✓ Branch 0 taken 562 times.
✗ Branch 1 not taken.
562 Item *item = kp->get_expression();
7881
7882 // Ensure that we aren't trying to index a field
7883
2/4
✓ Branch 0 taken 562 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 562 times.
562 assert(item->type() != Item::FIELD_ITEM);
7884
7885
1/2
✓ Branch 0 taken 562 times.
✗ Branch 1 not taken.
562 TABLE tmp_table;
7886
1/2
✓ Branch 0 taken 562 times.
✗ Branch 1 not taken.
562 TABLE_SHARE share;
7887 562 tmp_table.s = &share;
7888
1/2
✓ Branch 0 taken 562 times.
✗ Branch 1 not taken.
562 init_tmp_table_share(thd, &share, "", 0, "", "", nullptr);
7889
7890 562 tmp_table.s->db_create_options = 0;
7891 562 tmp_table.s->db_low_byte_first = false;
7892 562 tmp_table.set_not_started();
7893
7894
1/2
✓ Branch 0 taken 562 times.
✗ Branch 1 not taken.
562 Create_field *cr = generate_create_field(thd, item, &tmp_table);
7895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 562 times.
562 if (cr == nullptr) {
7896 return nullptr; /* purecov: deadcode */
7897 }
7898
7899
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 561 times.
562 if (is_blob(cr->sql_type)) {
7900
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_FUNCTIONAL_INDEX_ON_LOB, MYF(0));
7901 1 return nullptr;
7902 }
7903
7904 561 cr->field_name = field_name;
7905 561 cr->field = nullptr;
7906 561 cr->hidden = dd::Column::enum_hidden_type::HT_HIDDEN_SQL;
7907 561 cr->stored_in_db = false;
7908
7909
1/2
✓ Branch 0 taken 561 times.
✗ Branch 1 not taken.
1122 Value_generator *gcol_info = new (thd->mem_root) Value_generator();
7910
1/2
✓ Branch 0 taken 561 times.
✗ Branch 1 not taken.
561 gcol_info->expr_item = kp->get_expression();
7911 561 gcol_info->set_field_stored(false);
7912 561 gcol_info->set_field_type(cr->sql_type);
7913 561 cr->gcol_info = gcol_info;
7914
7915
2/2
✓ Branch 0 taken 560 times.
✓ Branch 1 taken 1 times.
561 if (is_not_slave_or_master_sorts_functional_index_columns_last(
7916 thd->variables.original_server_version)) {
7917 // Ensure that we insert the new hidden column in the correct place. That
7918 // is, hidden generated columns for functional indexes should be placed at
7919 // the end, sorted on their column name.
7920
1/2
✓ Branch 0 taken 560 times.
✗ Branch 1 not taken.
560 List_iterator<Create_field> insert_iterator(alter_info->create_list);
7921
5/8
✓ Branch 0 taken 560 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 560 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2522 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2006 times.
✓ Branch 7 taken 516 times.
2522 for (const Create_field &current : alter_info->create_list) {
7922
3/4
✓ Branch 0 taken 2006 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 383 times.
✓ Branch 3 taken 1623 times.
2006 if (is_field_for_functional_index(&current)) {
7923
1/2
✓ Branch 0 taken 383 times.
✗ Branch 1 not taken.
383 if (my_strcasecmp(system_charset_info, cr->field_name,
7924
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 339 times.
383 current.field_name) < 0) {
7925 44 break;
7926 }
7927 }
7928
7929 1962 insert_iterator++;
7930 }
7931
7932 // insert_iterator points to the last element where the field name is
7933 // "less than" the new Create_fields field name. So the correct place to
7934 // insert the new Create_field is _after_ the element that insert_iterator
7935 // points to.
7936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 560 times.
560 assert(!insert_iterator.is_before_first());
7937
1/2
✓ Branch 0 taken 560 times.
✗ Branch 1 not taken.
560 insert_iterator.after(cr);
7938 } else {
7939 // If the master doesn't sort functional index columns last, the slave
7940 // shouldn't do it either.
7941
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 alter_info->create_list.push_back(cr);
7942 }
7943
7944 561 alter_info->flags |= Alter_info::ALTER_ADD_COLUMN;
7945
1/2
✓ Branch 0 taken 561 times.
✗ Branch 1 not taken.
561 kp->set_name_and_prefix_length(field_name, 0);
7946 561 return cr;
7947 562 }
7948
7949 /**
7950 Check if the given column exists in the create list.
7951
7952 @param column_name the column name to look for.
7953 @param create_list the create list where the search is performed.
7954
7955 @retval true the column exists in the create list.
7956 @retval false the column does not exist in the create list.
7957 */
7958 309 static bool column_exists_in_create_list(const char *column_name,
7959 List<Create_field> &create_list) {
7960
4/8
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 309 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2596 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2596 times.
✗ Branch 7 not taken.
2596 for (const auto &it : create_list) {
7961
3/4
✓ Branch 0 taken 2596 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 309 times.
✓ Branch 3 taken 2287 times.
2596 if (my_strcasecmp(system_charset_info, column_name, it.field_name) == 0) {
7962 309 return true;
7963 }
7964 }
7965 return false;
7966 }
7967
7968 // Prepares the table and key structures for table creation.
7969 756937 bool mysql_prepare_create_table(
7970 THD *thd, const char *error_schema_name, const char *error_table_name,
7971 HA_CREATE_INFO *create_info, Alter_info *alter_info, handler *file,
7972 bool is_partitioned, KEY **key_info_buffer, uint *key_count,
7973 FOREIGN_KEY **fk_key_info_buffer, uint *fk_key_count,
7974 FOREIGN_KEY *existing_fks, uint existing_fks_count,
7975 const dd::Table *existing_fks_table, uint fk_max_generated_name_number,
7976 int select_field_count, bool find_parent_keys) {
7977
1/2
✓ Branch 0 taken 756943 times.
✗ Branch 1 not taken.
756937 DBUG_TRACE;
7978
7979 /*
7980 Validation of table properties.
7981 */
7982 756943 LEX_STRING *connect_string = &create_info->connect_string;
7983 1513967 if (connect_string->length != 0 &&
7984
4/6
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 756862 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 756943 times.
756943 connect_string->length > CONNECT_STRING_MAXLEN &&
7985 (system_charset_info->cset->charpos(
7986 system_charset_info, connect_string->str,
7987 (connect_string->str + connect_string->length),
7988 CONNECT_STRING_MAXLEN) < connect_string->length)) {
7989 my_error(ER_WRONG_STRING_LENGTH, MYF(0), connect_string->str, "CONNECTION",
7990 CONNECT_STRING_MAXLEN);
7991 return true;
7992 }
7993
7994 756943 LEX_STRING *compress = &create_info->compress;
7995
6/6
✓ Branch 0 taken 272 times.
✓ Branch 1 taken 756671 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 270 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 756941 times.
756945 if (compress->length != 0 && compress->length > TABLE_COMMENT_MAXLEN &&
7996 4 system_charset_info->cset->charpos(
7997
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 system_charset_info, compress->str, compress->str + compress->length,
7998
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 TABLE_COMMENT_MAXLEN) < compress->length) {
7999
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_WRONG_STRING_LENGTH, MYF(0), compress->str, "COMPRESSION",
8000 TABLE_COMMENT_MAXLEN);
8001 2 return true;
8002 }
8003
8004 756941 LEX_STRING *encrypt_type = &create_info->encrypt_type;
8005 1599181 if (encrypt_type->length != 0 &&
8006
4/6
✓ Branch 0 taken 85299 times.
✓ Branch 1 taken 671642 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 85299 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 756941 times.
756941 encrypt_type->length > TABLE_COMMENT_MAXLEN &&
8007 system_charset_info->cset->charpos(
8008 system_charset_info, encrypt_type->str,
8009 encrypt_type->str + encrypt_type->length,
8010 TABLE_COMMENT_MAXLEN) < encrypt_type->length) {
8011 my_error(ER_WRONG_STRING_LENGTH, MYF(0), encrypt_type->str, "ENCRYPTION",
8012 TABLE_COMMENT_MAXLEN);
8013 return true;
8014 }
8015
8016 // Validate table comment string
8017 756941 std::string invalid_sub_str;
8018
3/4
✓ Branch 0 taken 756932 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 756931 times.
756934 if (is_invalid_string({create_info->comment.str, create_info->comment.length},
8019 system_charset_info, invalid_sub_str)) {
8020
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 my_error(
8021 ER_COMMENT_CONTAINS_INVALID_STRING, MYF(0), "table",
8022
4/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
2 (std::string(error_schema_name) + "." + std::string(error_table_name))
8023 .c_str(),
8024 system_charset_info->csname, invalid_sub_str.c_str());
8025 1 return true;
8026 }
8027
8028
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 756928 times.
756932 if (validate_comment_length(
8029
1/2
✓ Branch 0 taken 756932 times.
✗ Branch 1 not taken.
756931 thd, create_info->comment.str, &create_info->comment.length,
8030 TABLE_COMMENT_MAXLEN, ER_TOO_LONG_TABLE_COMMENT, error_table_name)) {
8031 4 return true;
8032 }
8033
8034
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 756921 times.
756928 if (alter_info->create_list.elements > MAX_FIELDS) {
8035
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_error(ER_TOO_MANY_FIELDS, MYF(0));
8036 7 return true;
8037 }
8038
8039 /*
8040 Checks which previously were done during .FRM creation.
8041
8042 TODO: Check if the old .FRM limitations still make sense
8043 with the new DD.
8044 */
8045
8046 /* Fix this when we have new .frm files; Current limit is 4G rows (QQ) */
8047 756921 constexpr ulonglong u32max = UINT_MAX32;
8048
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 756918 times.
756921 if (create_info->max_rows > UINT_MAX32) {
8049 // Values larger than uint32_max are capped to uint32_max.
8050 // Emit a warning about this.
8051
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_VALUE_OUT_OF_RANGE,
8052 ER_THD(thd, ER_VALUE_OUT_OF_RANGE), "max_rows",
8053 create_info->max_rows, 0ULL, u32max, u32max);
8054 3 create_info->max_rows = UINT_MAX32;
8055 }
8056
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 756920 times.
756921 if (create_info->min_rows > UINT_MAX32) {
8057 // Values larger than uint32_max are capped to uint32_max.
8058 // Emit a warning about this.
8059
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_VALUE_OUT_OF_RANGE,
8060 ER_THD(thd, ER_VALUE_OUT_OF_RANGE), "min_rows",
8061 create_info->min_rows, 0ULL, u32max, u32max);
8062 1 create_info->min_rows = UINT_MAX32;
8063 }
8064
8065
2/2
✓ Branch 0 taken 439295 times.
✓ Branch 1 taken 317626 times.
756921 if (create_info->row_type == ROW_TYPE_DYNAMIC)
8066 439295 create_info->table_options |= HA_OPTION_PACK_RECORD;
8067
8068 /*
8069 Prepare fields, which must be done before calling
8070 add_functional_index_to_create_list(). The reason is that
8071 prepare_create_field() sets several properties of all Create_fields, such as
8072 character set. We need the character set in order to get the correct
8073 display width for each Create_field, which is in turn needed to resolve the
8074 correct data type/length for each hidden generated column added by
8075 add_functional_index_to_create_list().
8076 */
8077 756921 int select_field_pos = alter_info->create_list.elements - select_field_count;
8078 756921 create_info->null_bits = 0;
8079 756921 int field_no = 0;
8080 Create_field *sql_field;
8081
1/2
✓ Branch 0 taken 756921 times.
✗ Branch 1 not taken.
756921 List_iterator<Create_field> it(alter_info->create_list);
8082
2/2
✓ Branch 0 taken 6357202 times.
✓ Branch 1 taken 749507 times.
7106700 for (; (sql_field = it++); field_no++) {
8083
3/4
✓ Branch 0 taken 6357191 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7412 times.
✓ Branch 3 taken 6349779 times.
6357202 if (prepare_create_field(thd, error_schema_name, error_table_name,
8084 create_info, &alter_info->create_list,
8085 &select_field_pos, file, sql_field, field_no))
8086 7412 return true;
8087 }
8088
8089 // Go through all functional key parts. For each functional key part, resolve
8090 // the expression and add a hidden generated column to the create list.
8091
2/2
✓ Branch 0 taken 2691277 times.
✓ Branch 1 taken 749481 times.
3440759 for (Key_spec *key : alter_info->key_list) {
8092
2/2
✓ Branch 0 taken 612882 times.
✓ Branch 1 taken 2078395 times.
2691277 if (key->type == KEYTYPE_FOREIGN) continue;
8093
8094
2/2
✓ Branch 0 taken 2946310 times.
✓ Branch 1 taken 2078370 times.
5024680 for (size_t j = 0; j < key->columns.size(); ++j) {
8095
1/2
✓ Branch 0 taken 2946310 times.
✗ Branch 1 not taken.
2946310 Key_part_spec *key_part_spec = key->columns[j];
8096 // In the case of procedures, the Key_part_spec may both have an
8097 // expression and a field name assigned to it. But the hidden generated
8098 // will not exist in the create list, so we will have to add it.
8099
6/6
✓ Branch 0 taken 895 times.
✓ Branch 1 taken 2945415 times.
✓ Branch 2 taken 309 times.
✓ Branch 3 taken 586 times.
✓ Branch 4 taken 2945724 times.
✓ Branch 5 taken 586 times.
2947514 if (!key_part_spec->has_expression() ||
8100 895 (key_part_spec->get_field_name() != nullptr &&
8101
2/4
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 309 times.
✗ Branch 3 not taken.
309 column_exists_in_create_list(key_part_spec->get_field_name(),
8102 309 alter_info->create_list))) {
8103 2945724 continue;
8104 }
8105
8106
1/2
✓ Branch 0 taken 586 times.
✗ Branch 1 not taken.
586 Create_field *new_create_field = add_functional_index_to_create_list(
8107 thd, key, alter_info, key_part_spec, j, create_info);
8108
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 561 times.
586 if (new_create_field == nullptr) {
8109 25 return true;
8110 }
8111
8112 // Call prepare_create_field on the Create_field that was added by
8113 // add_functional_index_to_create_list().
8114
2/4
✓ Branch 0 taken 561 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 561 times.
561 assert(is_field_for_functional_index(new_create_field));
8115
2/4
✓ Branch 0 taken 561 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 561 times.
561 if (prepare_create_field(thd, error_schema_name, error_table_name,
8116 create_info, &alter_info->create_list,
8117 &select_field_pos, file, new_create_field,
8118 ++field_no)) {
8119 return true;
8120 }
8121 }
8122 }
8123
8124 // Now that we have all the Create_fields available, calculate the offsets
8125 // for each column.
8126
1/2
✓ Branch 0 taken 749488 times.
✗ Branch 1 not taken.
749481 calculate_field_offsets(&alter_info->create_list);
8127
8128 /*
8129 Auto increment and blob checks.
8130 */
8131 749488 int auto_increment = 0;
8132 749488 int blob_columns = 0;
8133 749488 it.rewind();
8134
2/2
✓ Branch 0 taken 6142801 times.
✓ Branch 1 taken 749483 times.
6892287 while ((sql_field = it++)) {
8135 /*
8136 Check if the column is compressible.
8137 VIRTUAL generated columns cannot have COMPRESSED attribute.
8138 */
8139 18423799 if ((sql_field->sql_type == MYSQL_TYPE_TINY_BLOB ||
8140
2/2
✓ Branch 0 taken 5771565 times.
✓ Branch 1 taken 366632 times.
6138197 sql_field->sql_type == MYSQL_TYPE_MEDIUM_BLOB ||
8141
2/2
✓ Branch 0 taken 5560327 times.
✓ Branch 1 taken 211238 times.
5771565 sql_field->sql_type == MYSQL_TYPE_BLOB ||
8142
2/2
✓ Branch 0 taken 5382600 times.
✓ Branch 1 taken 177727 times.
5560327 sql_field->sql_type == MYSQL_TYPE_LONG_BLOB ||
8143
2/2
✓ Branch 0 taken 4216241 times.
✓ Branch 1 taken 1166359 times.
5382600 sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
8144
6/6
✓ Branch 0 taken 6138197 times.
✓ Branch 1 taken 4604 times.
✓ Branch 2 taken 106105 times.
✓ Branch 3 taken 4110136 times.
✓ Branch 4 taken 2028816 times.
✓ Branch 5 taken 4113985 times.
12391707 sql_field->sql_type == MYSQL_TYPE_JSON) &&
8145
4/4
✓ Branch 0 taken 5113 times.
✓ Branch 1 taken 2027552 times.
✓ Branch 2 taken 1264 times.
✓ Branch 3 taken 3849 times.
2037778 (sql_field->gcol_info == nullptr ||
8146 5113 sql_field->gcol_info->get_field_stored())) {
8147
2/4
✓ Branch 0 taken 2028816 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2028816 times.
2028816 DBUG_EXECUTE_IF(
8148 "enforce_all_compressed_columns",
8149 sql_field->set_column_format(COLUMN_FORMAT_TYPE_COMPRESSED););
8150
8151 } else {
8152
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4113972 times.
4113985 if (sql_field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED) {
8153
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_UNSUPPORTED_COMPRESSED_COLUMN_TYPE, MYF(0),
8154 sql_field->field_name);
8155 4 return true;
8156 }
8157 }
8158
8159 /* Verify if the compression dictionary entry exists. Open compression
8160 dictionary table with MDL_SHARED_READ mode. If the entry exists,
8161 do not release the MDL lock. This is because we don't want a concurrent
8162 DROP COMPRESSION_DICTIONARY to remove the dictionary entry
8163 */
8164
8165 6142788 if (sql_field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED &&
8166
6/6
✓ Branch 0 taken 414 times.
✓ Branch 1 taken 6142381 times.
✓ Branch 2 taken 340 times.
✓ Branch 3 taken 74 times.
✓ Branch 4 taken 340 times.
✓ Branch 5 taken 6142455 times.
6143135 sql_field->zip_dict_name.str != nullptr &&
8167
1/2
✓ Branch 0 taken 340 times.
✗ Branch 1 not taken.
340 sql_field->zip_dict_name.length != 0) {
8168
2/4
✓ Branch 0 taken 340 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 340 times.
340 if (compression_dict::acquire_dict_mdl(thd, MDL_SHARED_READ)) {
8169 return true;
8170 }
8171
8172 uint64 zip_dict_id =
8173
1/2
✓ Branch 0 taken 340 times.
✗ Branch 1 not taken.
340 compression_dict::get_id_for_name(thd, sql_field->zip_dict_name);
8174
8175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 340 times.
340 if (zip_dict_id == 0) {
8176 my_error(ER_COMPRESSION_DICTIONARY_DOES_NOT_EXIST, MYF(0),
8177 sql_field->zip_dict_name.str);
8178 return true;
8179 }
8180 340 sql_field->zip_dict_id = zip_dict_id;
8181 }
8182
8183
2/2
✓ Branch 0 taken 245356 times.
✓ Branch 1 taken 5897439 times.
6142795 if (sql_field->auto_flags & Field::NEXT_NUMBER) auto_increment++;
8184
2/2
✓ Branch 0 taken 869010 times.
✓ Branch 1 taken 5273785 times.
6142795 switch (sql_field->sql_type) {
8185 869010 case MYSQL_TYPE_GEOMETRY:
8186 case MYSQL_TYPE_BLOB:
8187 case MYSQL_TYPE_MEDIUM_BLOB:
8188 case MYSQL_TYPE_TINY_BLOB:
8189 case MYSQL_TYPE_LONG_BLOB:
8190 case MYSQL_TYPE_JSON:
8191 869010 blob_columns++;
8192 869010 break;
8193 5273785 default:
8194
2/2
✓ Branch 0 taken 423 times.
✓ Branch 1 taken 5273362 times.
5273785 if (sql_field->is_array) blob_columns++;
8195 5273785 break;
8196 }
8197 }
8198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 749483 times.
749483 if (auto_increment > 1) {
8199 my_error(ER_WRONG_AUTO_KEY, MYF(0));
8200 return true;
8201 }
8202
4/6
✓ Branch 0 taken 245356 times.
✓ Branch 1 taken 504127 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 245356 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 749483 times.
749483 if (auto_increment && (file->ha_table_flags() & HA_NO_AUTO_INCREMENT)) {
8203 my_error(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT, MYF(0));
8204 return true;
8205 }
8206
4/6
✓ Branch 0 taken 338464 times.
✓ Branch 1 taken 411019 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 338464 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 749483 times.
749483 if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS)) {
8207 my_error(ER_TABLE_CANT_HANDLE_BLOB, MYF(0));
8208 return true;
8209 }
8210 /*
8211 CREATE TABLE[with auto_increment column] SELECT is unsafe as the rows
8212 inserted in the created table depends on the order of the rows fetched
8213 from the select tables. This order may differ on master and slave. We
8214 therefore mark it as unsafe.
8215 */
8216
4/4
✓ Branch 0 taken 9153 times.
✓ Branch 1 taken 740330 times.
✓ Branch 2 taken 92 times.
✓ Branch 3 taken 9061 times.
749483 if (select_field_count > 0 && auto_increment)
8217
1/2
✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
92 thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_CREATE_SELECT_AUTOINC);
8218
8219 /*
8220 Count keys and key segments.
8221 Also mark redundant keys to be ignored.
8222 */
8223 uint key_parts;
8224 Mem_root_array<bool> redundant_keys(thd->mem_root,
8225
1/2
✓ Branch 0 taken 749477 times.
✗ Branch 1 not taken.
1498961 alter_info->key_list.size(), false);
8226
3/4
✓ Branch 0 taken 749476 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 749468 times.
749477 if (count_keys(alter_info->key_list, key_count, &key_parts, fk_key_count,
8227 &redundant_keys, file->ha_table_flags()))
8228 8 return true;
8229
3/4
✓ Branch 0 taken 749472 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 749466 times.
749468 if (*key_count > file->max_keys()) {
8230
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 my_error(ER_TOO_MANY_KEYS, MYF(0), file->max_keys());
8231 6 return true;
8232 }
8233
8234 /*
8235 Make KEY objects for the keys in the new table.
8236 */
8237 KEY *key_info;
8238
1/2
✓ Branch 0 taken 749473 times.
✗ Branch 1 not taken.
749466 (*key_info_buffer) = key_info = (KEY *)sql_calloc(sizeof(KEY) * (*key_count));
8239 KEY_PART_INFO *key_part_info =
8240
1/2
✓ Branch 0 taken 749473 times.
✗ Branch 1 not taken.
749473 (KEY_PART_INFO *)sql_calloc(sizeof(KEY_PART_INFO) * key_parts);
8241
8242
2/4
✓ Branch 0 taken 749473 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 749473 times.
749473 if (!*key_info_buffer || !key_part_info) return true; // Out of memory
8243
8244 749473 alter_info->delayed_key_count = 0;
8245
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 749466 times.
749473 if (alter_info->delayed_key_list.size() > 0) {
8246 5 alter_info->delayed_key_info =
8247
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 static_cast<KEY *>(sql_calloc(sizeof(KEY) * (*key_count)));
8248 }
8249
8250
1/2
✓ Branch 0 taken 749465 times.
✗ Branch 1 not taken.
1498935 Mem_root_array<const KEY *> keys_to_check(thd->mem_root);
8251
2/4
✓ Branch 0 taken 749462 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 749462 times.
749465 if (keys_to_check.reserve(*key_count)) return true; // Out of memory
8252
8253 749462 uint key_number = 0;
8254 749462 bool primary_key = false;
8255
8256 // First prepare non-foreign keys so that they are ready when
8257 // we prepare foreign keys.
8258
2/2
✓ Branch 0 taken 2691136 times.
✓ Branch 1 taken 748090 times.
3439226 for (size_t i = 0; i < alter_info->key_list.size(); i++) {
8259
3/4
✓ Branch 0 taken 2691136 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 611693 times.
✓ Branch 3 taken 2079443 times.
2691136 if (redundant_keys[i]) continue; // Skip redundant keys
8260
8261
1/2
✓ Branch 0 taken 2079443 times.
✗ Branch 1 not taken.
2079443 const Key_spec *key = alter_info->key_list[i];
8262
8263
2/2
✓ Branch 0 taken 501007 times.
✓ Branch 1 taken 1578436 times.
2079443 if (key->type == KEYTYPE_PRIMARY) {
8264
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 500996 times.
501007 if (primary_key) {
8265
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 my_error(ER_MULTIPLE_PRI_KEY, MYF(0));
8266 11 return true;
8267 }
8268 500996 primary_key = true;
8269 }
8270
8271
2/2
✓ Branch 0 taken 1466550 times.
✓ Branch 1 taken 612882 times.
2079432 if (key->type != KEYTYPE_FOREIGN) {
8272
3/4
✓ Branch 0 taken 1466549 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1361 times.
✓ Branch 3 taken 1465188 times.
1466550 if (prepare_key(thd, error_schema_name, error_table_name, create_info,
8273 &alter_info->create_list, key, key_info_buffer, key_info,
8274 &key_part_info, keys_to_check, key_number, file,
8275 &auto_increment))
8276 1361 return true;
8277
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1465182 times.
1465191 for (const auto &it2 : alter_info->delayed_key_list) {
8278
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 if (it2 == key) {
8279 7 alter_info->delayed_key_info[alter_info->delayed_key_count++] =
8280 *key_info;
8281 7 break;
8282 }
8283 }
8284 1465189 key_info++;
8285 1465189 key_number++;
8286 }
8287 }
8288 // If the table is created without PK, we must check if this has
8289 // been disabled and return error. Limit the effect of sql_require_primary_key
8290 // to only those SEs that can participate in replication.
8291
2/2
✓ Branch 0 taken 173833 times.
✓ Branch 1 taken 73588 times.
247417 if (!primary_key && !thd->is_dd_system_thread() &&
8292
2/2
✓ Branch 0 taken 173254 times.
✓ Branch 1 taken 574 times.
173833 !thd->is_initialize_system_thread() &&
8293
2/2
✓ Branch 0 taken 155967 times.
✓ Branch 1 taken 17298 times.
173254 (file->ha_table_flags() &
8294 155967 (HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE)) != 0 &&
8295
6/6
✓ Branch 0 taken 247417 times.
✓ Branch 1 taken 500673 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 155952 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 748087 times.
995532 thd->variables.sql_require_primary_key &&
8296
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2 times.
15 !(create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
8297
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 my_error(ER_TABLE_WITHOUT_PK, MYF(0));
8298 13 return true;
8299 }
8300
8301 /*
8302 At this point all KEY objects are for indexes are fully constructed.
8303 So we can check for duplicate indexes for keys for which it was requested.
8304 */
8305 const KEY **dup_check_key;
8306 1677425 for (dup_check_key = keys_to_check.begin();
8307
3/4
✓ Branch 0 taken 1677421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 929338 times.
✓ Branch 3 taken 748083 times.
1677413 dup_check_key != keys_to_check.end(); dup_check_key++) {
8308
2/4
✓ Branch 0 taken 929338 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 929338 times.
929338 if (check_duplicate_key(thd, error_schema_name, error_table_name,
8309 *dup_check_key, *key_info_buffer, *key_count,
8310 alter_info))
8311 return true;
8312 }
8313
8314
7/8
✓ Branch 0 taken 247411 times.
✓ Branch 1 taken 500672 times.
✓ Branch 2 taken 247409 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 247408 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 748080 times.
748083 if (!primary_key && check_promoted_index(file, *key_info_buffer, *key_count))
8315 1 return true;
8316
8317 /*
8318 Any auto increment columns not found during prepare_key?
8319 */
8320
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 748072 times.
748080 if (auto_increment > 0) {
8321
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 my_error(ER_WRONG_AUTO_KEY, MYF(0));
8322 8 return true;
8323 }
8324
8325 /* Sort keys in optimized order */
8326
1/2
✓ Branch 0 taken 748074 times.
✗ Branch 1 not taken.
748072 std::sort(*key_info_buffer, *key_info_buffer + *key_count, sort_keys());
8327
8328 /*
8329 Normal keys are done, now prepare foreign keys.
8330
8331 We do this after sorting normal keys to get predictable behavior
8332 when searching for parent keys for self-referencing foreign keys.
8333 */
8334 748074 bool se_supports_fks =
8335 748074 (create_info->db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS);
8336
8337
3/4
✓ Branch 0 taken 121647 times.
✓ Branch 1 taken 626427 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 121647 times.
748074 assert(se_supports_fks || existing_fks_count == 0);
8338
8339 748074 (*fk_key_count) += existing_fks_count;
8340 FOREIGN_KEY *fk_key_info;
8341 748074 (*fk_key_info_buffer) = fk_key_info =
8342
1/2
✓ Branch 0 taken 748074 times.
✗ Branch 1 not taken.
748074 (FOREIGN_KEY *)sql_calloc(sizeof(FOREIGN_KEY) * (*fk_key_count));
8343
8344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 748074 times.
748074 if (!fk_key_info) return true; // Out of memory
8345
8346 // Copy pre-existing foreign keys.
8347
2/2
✓ Branch 0 taken 220 times.
✓ Branch 1 taken 747854 times.
748074 if (existing_fks_count > 0)
8348 220 memcpy(*fk_key_info_buffer, existing_fks,
8349 220 existing_fks_count * sizeof(FOREIGN_KEY));
8350 748074 uint fk_number = existing_fks_count;
8351 748074 fk_key_info += existing_fks_count;
8352
8353 /*
8354 Check if we are trying to add partitioning to the table with existing
8355 foreign keys and table's storage engine doesn't support foreign keys
8356 over partitioned tables.
8357 */
8358
6/6
✓ Branch 0 taken 6535 times.
✓ Branch 1 taken 741539 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6534 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 748073 times.
748075 if (is_partitioned && existing_fks_count > 0 &&
8359
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 (!create_info->db_type->partition_flags ||
8360
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 create_info->db_type->partition_flags() & HA_CANNOT_PARTITION_FK)) {
8361
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_FOREIGN_KEY_ON_PARTITIONED, MYF(0));
8362 1 return true;
8363 }
8364
8365 /*
8366 Check that definitions of existing foreign keys are not broken by this
8367 ALTER TABLE. Update FOREIGN_KEY::unique_constraint_name if necessary.
8368 */
8369 748314 for (FOREIGN_KEY *fk = *fk_key_info_buffer;
8370
2/2
✓ Branch 0 taken 264 times.
✓ Branch 1 taken 748050 times.
748314 fk < (*fk_key_info_buffer) + existing_fks_count; fk++) {
8371
3/4
✓ Branch 0 taken 264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 241 times.
264 if (prepare_preexisting_foreign_key(
8372 thd, create_info, alter_info, error_schema_name, error_table_name,
8373 *key_info_buffer, *key_count, existing_fks_table, fk))
8374 23 return true;
8375 }
8376
8377 // Prepare new foreign keys.
8378
2/2
✓ Branch 0 taken 2687453 times.
✓ Branch 1 taken 747974 times.
3435434 for (size_t i = 0; i < alter_info->key_list.size(); i++) {
8379
3/4
✓ Branch 0 taken 2687453 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 611654 times.
✓ Branch 3 taken 2075799 times.
2687453 if (redundant_keys[i]) continue; // Skip redundant keys
8380
8381
1/2
✓ Branch 0 taken 2075799 times.
✗ Branch 1 not taken.
2075799 Key_spec *key = alter_info->key_list[i];
8382
8383
2/2
✓ Branch 0 taken 612874 times.
✓ Branch 1 taken 1462925 times.
2075799 if (key->type == KEYTYPE_FOREIGN) {
8384
3/4
✓ Branch 0 taken 612874 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 612805 times.
612874 if (prepare_foreign_key(thd, create_info, alter_info, error_schema_name,
8385 error_table_name, is_partitioned,
8386 *key_info_buffer, *key_count, *fk_key_info_buffer,
8387 fk_number, se_supports_fks, find_parent_keys,
8388 down_cast<Foreign_key_spec *>(key),
8389 &fk_max_generated_name_number, fk_key_info))
8390 69 return true;
8391
8392
2/2
✓ Branch 0 taken 612771 times.
✓ Branch 1 taken 34 times.
612805 if (se_supports_fks) {
8393 612771 fk_key_info++;
8394 612771 fk_number++;
8395 }
8396 }
8397 }
8398
8399 /*
8400 Check if STRICT SQL mode is active and server is not started with
8401 --explicit-defaults-for-timestamp. Below check was added to prevent implicit
8402 default 0 value of timestamp. When explicit-defaults-for-timestamp server
8403 option is removed, whole set of check can be removed.
8404
8405 Note that this check must be after KEYs have been created as this
8406 can cause the NOT_NULL_FLAG to be set.
8407 */
8408
2/2
✓ Branch 0 taken 630029 times.
✓ Branch 1 taken 117945 times.
747974 if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
8409
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 629895 times.
630029 !thd->variables.explicit_defaults_for_timestamp) {
8410 134 it.rewind();
8411
2/2
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 134 times.
420 while ((sql_field = it++)) {
8412
3/4
✓ Branch 0 taken 271 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 237 times.
542 if (!sql_field->constant_default && !sql_field->gcol_info &&
8413 271 is_timestamp_type(sql_field->sql_type) &&
8414
5/6
✓ Branch 0 taken 271 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 286 times.
569 (sql_field->flags & NOT_NULL_FLAG) &&
8415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 !(sql_field->auto_flags & Field::DEFAULT_NOW)) {
8416 /*
8417 An error should be reported if:
8418 - there is no explicit DEFAULT clause (default column value);
8419 - this is a TIMESTAMP column;
8420 - the column is not NULL;
8421 - this is not the DEFAULT CURRENT_TIMESTAMP column.
8422 And from checks before while loop,
8423 - STRICT SQL mode is active;
8424 - server is not started with --explicit-defaults-for-timestamp
8425
8426 In other words, an error should be reported if
8427 - STRICT SQL mode is active;
8428 - the column definition is equivalent to
8429 'column_name TIMESTAMP DEFAULT 0'.
8430 */
8431
8432 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
8433 return true;
8434 }
8435 }
8436 }
8437
8438 /* If fixed row records, we need one bit to check for deleted rows */
8439
2/2
✓ Branch 0 taken 138676 times.
✓ Branch 1 taken 609298 times.
747974 if (!(create_info->table_options & HA_OPTION_PACK_RECORD))
8440 138676 create_info->null_bits++;
8441 747974 ulong data_offset = (create_info->null_bits + 7) / 8;
8442 747974 size_t reclength = data_offset;
8443 747974 it.rewind();
8444
2/2
✓ Branch 0 taken 6138618 times.
✓ Branch 1 taken 747981 times.
6886597 while ((sql_field = it++)) {
8445
1/2
✓ Branch 0 taken 6138618 times.
✗ Branch 1 not taken.
6138618 size_t length = sql_field->pack_length();
8446
2/2
✓ Branch 0 taken 6136383 times.
✓ Branch 1 taken 2235 times.
6138618 if (sql_field->offset + data_offset + length > reclength)
8447 6136383 reclength = sql_field->offset + data_offset + length;
8448 }
8449
3/4
✓ Branch 0 taken 747977 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 747970 times.
747981 if (reclength > file->max_record_length()) {
8450 7 my_error(ER_TOO_BIG_ROWSIZE, MYF(0),
8451
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 static_cast<long>(file->max_record_length()));
8452 7 return true;
8453 }
8454
8455 747970 return false;
8456 756932 }
8457
8458 /**
8459 @brief check comment length of table, column, index and partition
8460
8461 @details If comment length is more than the standard length
8462 truncate it and store the comment length up to the standard
8463 comment length size
8464
8465 @param thd Thread handle
8466 @param comment_str Comment string
8467 @param[in,out] comment_len Comment length
8468 @param max_len Maximum allowed comment length
8469 @param err_code Error message
8470 @param comment_name Type of comment
8471
8472 @return Operation status
8473 @retval true Error found
8474 @retval false On success
8475 */
8476
8477 8609005 bool validate_comment_length(THD *thd, const char *comment_str,
8478 size_t *comment_len, uint max_len, uint err_code,
8479 const char *comment_name) {
8480 8609005 size_t length = 0;
8481
1/2
✓ Branch 0 taken 8609025 times.
✗ Branch 1 not taken.
8609005 DBUG_TRACE;
8482
8483
2/2
✓ Branch 0 taken 2167065 times.
✓ Branch 1 taken 6441960 times.
8609025 if (comment_str == nullptr) {
8484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2167065 times.
2167065 assert(*comment_len == 0);
8485 2167065 return false;
8486 }
8487 12883923 size_t tmp_len = system_charset_info->cset->charpos(
8488
1/2
✓ Branch 0 taken 6441963 times.
✗ Branch 1 not taken.
6441960 system_charset_info, comment_str, comment_str + *comment_len, max_len);
8489
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6441922 times.
6441963 if (tmp_len < *comment_len) {
8490
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 23 times.
41 if (thd->is_strict_mode()) {
8491
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 my_error(err_code, MYF(0), comment_name, static_cast<ulong>(max_len));
8492 18 return true;
8493 }
8494 char warn_buff[MYSQL_ERRMSG_SIZE];
8495 23 length =
8496
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 snprintf(warn_buff, sizeof(warn_buff), ER_THD_NONCONST(thd, err_code),
8497 comment_name, static_cast<ulong>(max_len));
8498 /* do not push duplicate warnings */
8499
2/4
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
23 if (!thd->get_stmt_da()->has_sql_condition(warn_buff, length))
8500
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 push_warning(thd, Sql_condition::SL_WARNING, err_code, warn_buff);
8501 23 *comment_len = tmp_len;
8502 }
8503 6441945 return false;
8504 8609028 }
8505
8506 /*
8507 Set table default charset, if not set
8508
8509 SYNOPSIS
8510 set_table_default_charset()
8511 create_info Table create information
8512
8513 DESCRIPTION
8514 If the table character set was not given explicitly,
8515 let's fetch the database default character set and
8516 apply it to the table.
8517 */
8518
8519 847602 static bool set_table_default_charset(THD *thd, HA_CREATE_INFO *create_info,
8520 const dd::Schema &schema) {
8521 /*
8522 If the table character set was not given explicitly,
8523 let's fetch the database default character set and
8524 apply it to the table.
8525 */
8526
2/2
✓ Branch 0 taken 236212 times.
✓ Branch 1 taken 611390 times.
847602 if (create_info->default_table_charset == nullptr) {
8527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 236214 times.
236212 if (get_default_db_collation(schema, &create_info->default_table_charset))
8528 return true;
8529 } else {
8530
3/6
✓ Branch 0 taken 3904 times.
✓ Branch 1 taken 607486 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3904 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
611390 assert((create_info->used_fields & HA_CREATE_USED_CHARSET) == 0 ||
8531 (create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) ||
8532 create_info->default_table_charset == create_info->table_charset);
8533
8534
2/2
✓ Branch 0 taken 438733 times.
✓ Branch 1 taken 172657 times.
611390 if ((create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) &&
8535
2/2
✓ Branch 0 taken 18480 times.
✓ Branch 1 taken 420253 times.
438733 !(create_info->used_fields & HA_CREATE_USED_DEFAULT_COLLATE) &&
8536
2/2
✓ Branch 0 taken 3523 times.
✓ Branch 1 taken 14957 times.
18480 create_info->default_table_charset == &my_charset_utf8mb4_0900_ai_ci) {
8537 3523 create_info->default_table_charset =
8538 3523 thd->variables.default_collation_for_utf8mb4;
8539
8540 // ALTER TABLE ... CONVERT TO CHARACTER SET ...
8541
2/2
✓ Branch 0 taken 328 times.
✓ Branch 1 taken 3195 times.
3523 if (create_info->used_fields & HA_CREATE_USED_CHARSET) {
8542 328 create_info->table_charset = create_info->default_table_charset;
8543 }
8544 }
8545 }
8546
8547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 847604 times.
847604 if (create_info->default_table_charset == nullptr)
8548 create_info->default_table_charset = thd->collation();
8549
8550 847604 return false;
8551 }
8552
8553 /*
8554 Extend long VARCHAR fields to blob & prepare field if it's a blob
8555
8556 SYNOPSIS
8557 prepare_blob_field()
8558 sql_field Field to check
8559
8560 RETURN
8561 0 ok
8562 1 Error (sql_field can't be converted to blob)
8563 In this case the error is given
8564 */
8565
8566 6757305 static bool prepare_blob_field(THD *thd, Create_field *sql_field,
8567 bool convert_character_set) {
8568
1/2
✓ Branch 0 taken 6757318 times.
✗ Branch 1 not taken.
6757305 DBUG_TRACE;
8569
8570 // Skip typed array fields
8571
2/2
✓ Branch 0 taken 423 times.
✓ Branch 1 taken 6756895 times.
6757318 if (sql_field->is_array) return false;
8572
8573
5/6
✓ Branch 0 taken 6756884 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 705993 times.
✓ Branch 3 taken 6050891 times.
✓ Branch 4 taken 25 times.
✓ Branch 5 taken 6756859 times.
7462888 if (sql_field->max_display_width_in_bytes() > MAX_FIELD_VARCHARLENGTH &&
8574
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 705968 times.
705993 !(sql_field->flags & BLOB_FLAG)) {
8575 /* Convert long VARCHAR columns to TEXT or BLOB */
8576 char warn_buff[MYSQL_ERRMSG_SIZE];
8577
8578
5/6
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 16 times.
25 if (sql_field->constant_default || thd->is_strict_mode()) {
8579 9 my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
8580 9 static_cast<ulong>(MAX_FIELD_VARCHARLENGTH /
8581
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 sql_field->charset->mbmaxlen));
8582 9 return true;
8583 }
8584 16 sql_field->sql_type =
8585
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 get_blob_type_from_length(sql_field->max_display_width_in_bytes());
8586 16 sql_field->flags |= BLOB_FLAG;
8587
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
32 snprintf(warn_buff, sizeof(warn_buff), ER_THD(thd, ER_AUTO_CONVERT),
8588 sql_field->field_name,
8589
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12 times.
16 (sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
8590
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12 times.
16 (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
8591
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 push_warning(thd, Sql_condition::SL_NOTE, ER_AUTO_CONVERT, warn_buff);
8592 }
8593
8594 /*
8595 If the user has given a length to the BLOB/TEXT column explicitly, we make
8596 sure that we choose the most appropriate data type. For instance, "TEXT(63)
8597 CHARACTER SET utf8mb4" is automatically converted to TINYTEXT since TINYTEXT
8598 can hold 255 _bytes_ of data (which is enough for 63 _characters_ of
8599 utf8mb4).
8600
8601 Also, if we are changing the character set to a character set that requires
8602 more storage per character, we might need to change the column to a bigger
8603 type in order to not loose any data. Consider the following example:
8604
8605 CREATE TABLE t1 (a TINYTEXT CHARACTER SET latin1);
8606 ALTER TABLE t1 CONVERT TO CHARACTER SET utf8mb4;
8607
8608 TINYTEXT can store up to 255 _bytes_ of data, and since "latin1" requires
8609 one byte per character the user can store 255 _characters_ into this column.
8610 If we are changing the character set to utf8mb4, each character suddenly
8611 requires 4 bytes of storage. So an existing string in the column "a" that
8612 is 255 characters long now suddenly requires 1020 _bytes_ of storage. This
8613 does not fit into TINYTEXT, so we need to switch the data type to TEXT in
8614 order not to loose any existing data (TEXT can store up to 65536 _bytes_ of
8615 data, which is 16384 _characters_ of utf8mb4 data).
8616 */
8617
2/2
✓ Branch 0 taken 1001028 times.
✓ Branch 1 taken 5755847 times.
6756875 if ((sql_field->flags & BLOB_FLAG) &&
8618
2/2
✓ Branch 0 taken 709860 times.
✓ Branch 1 taken 291168 times.
1001028 (sql_field->sql_type == FIELD_TYPE_BLOB ||
8619
2/2
✓ Branch 0 taken 705936 times.
✓ Branch 1 taken 3924 times.
709860 sql_field->sql_type == FIELD_TYPE_TINY_BLOB ||
8620
2/2
✓ Branch 0 taken 367378 times.
✓ Branch 1 taken 338558 times.
705936 sql_field->sql_type == FIELD_TYPE_MEDIUM_BLOB)) {
8621
2/2
✓ Branch 0 taken 1306 times.
✓ Branch 1 taken 661161 times.
662470 if (sql_field->explicit_display_width()) {
8622 1306 sql_field->sql_type =
8623
2/4
✓ Branch 0 taken 1306 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1306 times.
✗ Branch 3 not taken.
1306 get_blob_type_from_length(sql_field->max_display_width_in_bytes());
8624
3/4
✓ Branch 0 taken 1269 times.
✓ Branch 1 taken 659892 times.
✓ Branch 2 taken 1269 times.
✗ Branch 3 not taken.
661161 } else if (convert_character_set && sql_field->field != nullptr) {
8625 // If sql_field->field == nullptr, it means that we are doing a "CONVERT
8626 // TO CHARACTER SET" _and_ adding a new column in the same statement.
8627 // The new column will have the new correct character set, so we don't
8628 // need to do anything for that column here.
8629 const size_t max_codepoints_old_field =
8630
1/2
✓ Branch 0 taken 1269 times.
✗ Branch 1 not taken.
1269 sql_field->field->char_length() /
8631
1/2
✓ Branch 0 taken 1269 times.
✗ Branch 1 not taken.
1269 sql_field->field->charset()->mbmaxlen;
8632 1269 const size_t max_bytes_new_field =
8633 1269 max_codepoints_old_field * sql_field->charset->mbmaxlen;
8634
1/2
✓ Branch 0 taken 1269 times.
✗ Branch 1 not taken.
1269 sql_field->sql_type = get_blob_type_from_length(max_bytes_new_field);
8635 }
8636 }
8637
8638 6756872 return false;
8639 6757304 }
8640
8641 /**
8642 Struct for representing the result of checking if a table exists
8643 before trying to create it. The result has two different
8644 dimensions; if the table actually exists, and if an error
8645 occurred. If the table exists m_error will still be false if this is
8646 CREATE IF NOT EXISTS.
8647 */
8648 struct Table_exists_result {
8649 /** true if the table already exists */
8650 bool m_table_exists;
8651
8652 /** true if my_error() has been called and an error must be propagated. */
8653 bool m_error;
8654 };
8655
8656 /**
8657 Check if table already exists.
8658
8659 @param thd thread handle
8660 @param schema_name schema name.
8661 @param table_name table name.
8662 @param alias alt representation of table_name.
8663 @param ha_lex_create_tmp_table true if creating a tmp table.
8664 @param ha_create_if_not_exists true if this is CREATE IF NOT EXISTS.
8665 @param internal_tmp_table true if this is an internal tmp table.
8666
8667 @return false if successful, true otherwise.
8668 */
8669 758795 static Table_exists_result check_if_table_exists(
8670 THD *thd, const char *schema_name, const char *table_name,
8671 const char *alias, bool ha_lex_create_tmp_table,
8672 bool ha_create_if_not_exists, bool internal_tmp_table) {
8673
4/4
✓ Branch 0 taken 52543 times.
✓ Branch 1 taken 706252 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 758724 times.
811338 if (ha_lex_create_tmp_table &&
8674
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 52472 times.
52543 find_temporary_table(thd, schema_name, table_name)) {
8675
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 16 times.
71 if (ha_create_if_not_exists) {
8676 55 push_warning_printf(thd, Sql_condition::SL_NOTE, ER_TABLE_EXISTS_ERROR,
8677 ER_THD(thd, ER_TABLE_EXISTS_ERROR), alias);
8678 55 return {true, false};
8679 }
8680 16 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
8681 16 return {true, true};
8682 }
8683
8684
4/4
✓ Branch 0 taken 670826 times.
✓ Branch 1 taken 87898 times.
✓ Branch 2 taken 619515 times.
✓ Branch 3 taken 51311 times.
1378249 if (!internal_tmp_table && !ha_lex_create_tmp_table &&
8685
12/20
✓ Branch 0 taken 619518 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 619524 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 619525 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 619525 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 213180 times.
✓ Branch 9 taken 406345 times.
✓ Branch 10 taken 619523 times.
✓ Branch 11 taken 139211 times.
✓ Branch 12 taken 619524 times.
✓ Branch 13 taken 139211 times.
✓ Branch 14 taken 213179 times.
✓ Branch 15 taken 545560 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
1378249 !dd::get_dictionary()->is_dd_table_name(schema_name, table_name)) {
8686 213179 const dd::Abstract_table *at = nullptr;
8687
4/8
✓ Branch 0 taken 213181 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 213181 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 213175 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 213178 times.
213179 if (thd->dd_client()->acquire(schema_name, table_name, &at)) {
8688 6357 return {false, true};
8689 }
8690
8691
2/2
✓ Branch 0 taken 6357 times.
✓ Branch 1 taken 206821 times.
213178 if (at != nullptr) {
8692
2/2
✓ Branch 0 taken 5269 times.
✓ Branch 1 taken 1088 times.
6357 if (ha_create_if_not_exists) {
8693
2/4
✓ Branch 0 taken 5269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5269 times.
✗ Branch 3 not taken.
5269 push_warning_printf(thd, Sql_condition::SL_NOTE, ER_TABLE_EXISTS_ERROR,
8694 ER_THD(thd, ER_TABLE_EXISTS_ERROR), alias);
8695 5269 return {true, false};
8696 }
8697
1/2
✓ Branch 0 taken 1088 times.
✗ Branch 1 not taken.
1088 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
8698 1088 return {true, true};
8699 }
8700 }
8701
8702 /*
8703 Check that table with given name does not already
8704 exist in any storage engine. In such a case it should
8705 be discovered and the error ER_TABLE_EXISTS_ERROR be returned
8706 unless user specified CREATE TABLE IF EXISTS
8707 An exclusive metadata lock ensures that no
8708 one else is attempting to discover the table. Since
8709 it's not on disk as a frm file, no one could be using it!
8710 */
8711
2/2
✓ Branch 0 taken 699908 times.
✓ Branch 1 taken 52473 times.
1452290 if (!ha_lex_create_tmp_table &&
8712
12/20
✓ Branch 0 taken 699908 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 699910 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 699911 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 699909 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 293565 times.
✓ Branch 9 taken 406344 times.
✓ Branch 10 taken 699910 times.
✓ Branch 11 taken 52472 times.
✓ Branch 12 taken 699912 times.
✓ Branch 13 taken 52472 times.
✓ Branch 14 taken 293567 times.
✓ Branch 15 taken 458817 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
1452290 !dd::get_dictionary()->is_dd_table_name(schema_name, table_name)) {
8713 293567 int retcode = ha_table_exists_in_engine(thd, schema_name, table_name);
8714
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 293544 times.
293567 DBUG_PRINT("info", ("exists_in_engine: %u", retcode));
8715
1/3
✓ Branch 0 taken 293567 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
293567 switch (retcode) {
8716 293567 case HA_ERR_NO_SUCH_TABLE:
8717 /* Normal case, no table exists. we can go and create it */
8718 293567 break;
8719
8720 case HA_ERR_TABLE_EXIST:
8721 DBUG_PRINT("info", ("Table existed in handler"));
8722
8723 if (ha_create_if_not_exists) {
8724 push_warning_printf(thd, Sql_condition::SL_NOTE,
8725 ER_TABLE_EXISTS_ERROR,
8726 ER_THD(thd, ER_TABLE_EXISTS_ERROR), alias);
8727 return {true, false};
8728 }
8729 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
8730 return {true, true};
8731 break;
8732
8733 default:
8734 DBUG_PRINT("info", ("error: %u from storage engine", retcode));
8735 my_error(retcode, MYF(0), table_name);
8736 return {true, true};
8737 }
8738 }
8739 752384 return {false, false};
8740 }
8741
8742 /**
8743 Create a table
8744
8745 @param thd Thread object
8746 @param schema DD schema object
8747 @param db Database
8748 @param table_name Table name
8749 @param error_table_name The real table name in case table_name is a
8750 temporary table (ALTER). Used for error messages and for checking whether the
8751 table is a white listed system table.
8752 @param path Path to table (i.e. to its .FRM file without
8753 the extension).
8754 @param create_info Create information (like MAX_ROWS)
8755 @param alter_info Description of fields and keys for new table
8756 @param internal_tmp_table Set to true if this is an internal temporary table
8757 (From ALTER TABLE)
8758 @param select_field_count Number of fields coming from SELECT part of
8759 CREATE TABLE ... SELECT statement. Must be zero
8760 for standard create of table.
8761 @param find_parent_keys Indicates whether we need to lookup name of unique
8762 constraint in parent table for foreign keys.
8763 @param no_ha_table Indicates that only .FRM file (and PAR file if
8764 table is partitioned) needs to be created and not a table in the storage
8765 engine.
8766 @param do_not_store_in_dd Indicates that we should postpone storing table
8767 object in the data-dictionary. Requires SE
8768 supporting atomic DDL and no_ha_table flag set.
8769 @param[out] is_trans Identifies the type of engine where the table
8770 was created: either trans or non-trans.
8771 @param[out] key_info Array of KEY objects describing keys in table
8772 which was created.
8773 @param[out] key_count Number of keys in table which was created.
8774 @param keys_onoff Enable or disable keys.
8775 @param[out] fk_key_info Array of FOREIGN_KEY objects describing foreign
8776 keys in table which was created.
8777 @param[out] fk_key_count Number of foreign keys in table which was created.
8778 @param[in] existing_fk_info Array of FOREIGN_KEY objects for foreign keys
8779 which already existed in the table
8780 (in case of ALTER TABLE).
8781 @param[in] existing_fk_count Number of pre-existing foreign keys.
8782 @param[in] existing_fk_table dd::Table object for table version from which
8783 pre-existing foreign keys come from. Needed
8784 for error reporting.
8785 @param[in] fk_max_generated_name_number Max value of number component among
8786 existing generated foreign key names.
8787 @param[out] table_def Data-dictionary object describing the table
8788 created if do_not_store_in_dd option was
8789 used or because the table is temporary and
8790 was not open due to no_ha_table. Not set
8791 otherwise.
8792 @param[out] post_ddl_ht Set to handlerton for table's SE, if this SE
8793 supports atomic DDL, so caller can call SE
8794 post DDL hook after committing transaction.
8795
8796 If one creates a temporary table, this is automatically opened
8797
8798 Note that this function assumes that caller already have taken
8799 exclusive metadata lock on table being created or used some other
8800 way to ensure that concurrent operations won't intervene.
8801 mysql_create_table() is a wrapper that can be used for this.
8802
8803 @note On failure, for engines supporting atomic DDL, the caller must
8804 rollback statement and transaction before doing anything else.
8805
8806 @retval false OK
8807 @retval true error
8808 */
8809
8810 759419 static bool create_table_impl(
8811 THD *thd, const dd::Schema &schema, const char *db, const char *table_name,
8812 const char *error_table_name, const char *path, HA_CREATE_INFO *create_info,
8813 Alter_info *alter_info, bool internal_tmp_table, uint select_field_count,
8814 bool find_parent_keys, bool no_ha_table, bool do_not_store_in_dd,
8815 bool *is_trans, KEY **key_info, uint *key_count,
8816 Alter_info::enum_enable_or_disable keys_onoff, FOREIGN_KEY **fk_key_info,
8817 uint *fk_key_count, FOREIGN_KEY *existing_fk_info, uint existing_fk_count,
8818 const dd::Table *existing_fk_table, uint fk_max_generated_name_number,
8819 std::unique_ptr<dd::Table> *table_def, handlerton **post_ddl_ht) {
8820
1/2
✓ Branch 0 taken 759433 times.
✗ Branch 1 not taken.
759419 DBUG_TRACE;
8821
5/8
✓ Branch 0 taken 759431 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 759434 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21 times.
✓ Branch 5 taken 759413 times.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
759433 DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d", db, table_name,
8822 internal_tmp_table));
8823
8824 // Check that we have at least one visible column.
8825 759434 bool has_visible_column = false;
8826
5/8
✓ Branch 0 taken 759435 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 759433 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 759687 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 759680 times.
✓ Branch 7 taken 7 times.
759688 for (const Create_field &create_field : alter_info->create_list) {
8827
2/2
✓ Branch 0 taken 759426 times.
✓ Branch 1 taken 254 times.
759680 if (create_field.hidden == dd::Column::enum_hidden_type::HT_VISIBLE) {
8828 759426 has_visible_column = true;
8829 759426 break;
8830 }
8831 }
8832
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 759427 times.
759433 if (!has_visible_column) {
8833
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(ER_TABLE_MUST_HAVE_A_VISIBLE_COLUMN, MYF(0));
8834 6 return true;
8835 }
8836
8837
3/4
✓ Branch 0 taken 759426 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 759374 times.
759427 if (check_engine(thd, db, table_name, create_info, alter_info)) return true;
8838
8839 // Secondary engine cannot be defined for temporary tables.
8840
2/2
✓ Branch 0 taken 119 times.
✓ Branch 1 taken 759255 times.
759374 if (create_info->secondary_engine.str != nullptr &&
8841
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 117 times.
119 create_info->options & HA_LEX_CREATE_TMP_TABLE) {
8842
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_SECONDARY_ENGINE, MYF(0), "Temporary tables not supported");
8843 2 return true;
8844 }
8845
8846
2/4
✓ Branch 0 taken 759359 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 759359 times.
759372 if (set_table_default_charset(thd, create_info, schema)) return true;
8847
8848
1/2
✓ Branch 0 taken 759366 times.
✗ Branch 1 not taken.
759359 const char *alias = table_case_name(create_info, table_name);
8849
8850 759366 partition_info *part_info = thd->work_part_info;
8851
8852 std::unique_ptr<handler, Destroy_only<handler>> file(get_new_handler(
8853 (TABLE_SHARE *)nullptr,
8854 759369 (part_info ||
8855
2/2
✓ Branch 0 taken 638117 times.
✓ Branch 1 taken 114241 times.
752358 (create_info->db_type->partition_flags &&
8856
3/4
✓ Branch 0 taken 638120 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 638116 times.
638117 (create_info->db_type->partition_flags() & HA_USE_AUTO_PARTITION))),
8857
3/4
✓ Branch 0 taken 752358 times.
✓ Branch 1 taken 7008 times.
✓ Branch 2 taken 759372 times.
✗ Branch 3 not taken.
1518735 thd->mem_root, create_info->db_type));
8858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 759373 times.
759376 if (file.get() == nullptr) {
8859 mem_alloc_error(sizeof(handler));
8860 return true;
8861 }
8862
8863
5/6
✓ Branch 0 taken 752359 times.
✓ Branch 1 taken 7014 times.
✓ Branch 2 taken 638121 times.
✓ Branch 3 taken 114238 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 759373 times.
1397494 if (!part_info && create_info->db_type->partition_flags &&
8864
2/4
✓ Branch 0 taken 638121 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 638121 times.
638121 (create_info->db_type->partition_flags() & HA_USE_AUTO_PARTITION)) {
8865 Partition_handler *part_handler = file->get_partition_handler();
8866 assert(part_handler != nullptr);
8867
8868 /*
8869 Table is not defined as a partitioned table but the engine handles
8870 all tables as partitioned. The handler will set up the partition info
8871 object with the default settings.
8872 */
8873 thd->work_part_info = part_info = new (thd->mem_root) partition_info();
8874 if (!part_info) {
8875 mem_alloc_error(sizeof(partition_info));
8876 return true;
8877 }
8878 part_handler->set_auto_partitions(part_info);
8879 part_info->default_engine_type = create_info->db_type;
8880 part_info->is_auto_partitioned = true;
8881 }
8882
2/2
✓ Branch 0 taken 7012 times.
✓ Branch 1 taken 752361 times.
759373 if (part_info) {
8883 /*
8884 The table has been specified as a partitioned table.
8885 If this is part of an ALTER TABLE the handler will be the partition
8886 handler but we need to specify the default handler to use for
8887 partitions also in the call to check_partition_info. We transport
8888 this information in the default_db_type variable, it is either
8889 DB_TYPE_DEFAULT or the engine set in the ALTER TABLE command.
8890 */
8891 handlerton *engine_type;
8892
1/2
✓ Branch 0 taken 7012 times.
✗ Branch 1 not taken.
7012 List_iterator<partition_element> part_it(part_info->partitions);
8893 partition_element *part_elem;
8894
8895
2/2
✓ Branch 0 taken 17305 times.
✓ Branch 1 taken 7012 times.
24317 while ((part_elem = part_it++)) {
8896
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 17276 times.
17305 if (part_elem->part_comment) {
8897 29 size_t comment_len = strlen(part_elem->part_comment);
8898
8899 // Validate partition comment string
8900 29 std::string invalid_sub_str;
8901
2/4
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 29 times.
29 if (is_invalid_string({part_elem->part_comment, comment_len},
8902 system_charset_info, invalid_sub_str)) {
8903 my_error(ER_COMMENT_CONTAINS_INVALID_STRING, MYF(0), "partition",
8904 (std::string(db) + "." + std::string(error_table_name) +
8905 "." + std::string(part_elem->partition_name))
8906 .c_str(),
8907 system_charset_info->csname, invalid_sub_str.c_str());
8908 return true;
8909 }
8910
8911
2/4
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 29 times.
29 if (validate_comment_length(thd, part_elem->part_comment, &comment_len,
8912 TABLE_PARTITION_COMMENT_MAXLEN,
8913 ER_TOO_LONG_TABLE_PARTITION_COMMENT,
8914 part_elem->partition_name))
8915 return true;
8916 29 part_elem->part_comment[comment_len] = '\0';
8917
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 }
8918
2/2
✓ Branch 0 taken 2215 times.
✓ Branch 1 taken 15090 times.
17305 if (part_elem->subpartitions.elements) {
8919
1/2
✓ Branch 0 taken 2215 times.
✗ Branch 1 not taken.
2215 List_iterator<partition_element> sub_it(part_elem->subpartitions);
8920 partition_element *subpart_elem;
8921
2/2
✓ Branch 0 taken 5194 times.
✓ Branch 1 taken 2215 times.
7409 while ((subpart_elem = sub_it++)) {
8922
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5183 times.
5194 if (subpart_elem->part_comment) {
8923 11 size_t comment_len = strlen(subpart_elem->part_comment);
8924
8925 // Validate subpartition comment string
8926 11 std::string invalid_sub_str;
8927
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if (is_invalid_string({subpart_elem->part_comment, comment_len},
8928 system_charset_info, invalid_sub_str)) {
8929 my_error(ER_COMMENT_CONTAINS_INVALID_STRING, MYF(0),
8930 "subpartition",
8931 (std::string(db) + "." + std::string(error_table_name) +
8932 "." + std::string(part_elem->partition_name) + "." +
8933 std::string(subpart_elem->partition_name))
8934 .c_str(),
8935 system_charset_info->csname, invalid_sub_str.c_str());
8936 return true;
8937 }
8938
8939
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if (validate_comment_length(thd, subpart_elem->part_comment,
8940 &comment_len,
8941 TABLE_PARTITION_COMMENT_MAXLEN,
8942 ER_TOO_LONG_TABLE_PARTITION_COMMENT,
8943 subpart_elem->partition_name))
8944 return true;
8945 11 subpart_elem->part_comment[comment_len] = '\0';
8946
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 }
8947 }
8948 }
8949 }
8950
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7009 times.
7012 if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
8951
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_PARTITION_NO_TEMPORARY, MYF(0));
8952 3 return true;
8953 }
8954
2/2
✓ Branch 0 taken 1650 times.
✓ Branch 1 taken 5359 times.
7009 if (create_info->used_fields & HA_CREATE_USED_ENGINE) {
8955 1650 part_info->default_engine_type = create_info->db_type;
8956 } else {
8957
2/2
✓ Branch 0 taken 2433 times.
✓ Branch 1 taken 2926 times.
5359 if (part_info->default_engine_type == nullptr) {
8958 2433 part_info->default_engine_type =
8959
1/2
✓ Branch 0 taken 2433 times.
✗ Branch 1 not taken.
2433 ha_checktype(thd, DB_TYPE_DEFAULT, false, false);
8960 }
8961 }
8962
3/12
✓ Branch 0 taken 7009 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7009 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7009 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
7009 DBUG_PRINT("info",
8963 ("db_type = %s create_info->db_type = %s",
8964 ha_resolve_storage_engine_name(part_info->default_engine_type),
8965 ha_resolve_storage_engine_name(create_info->db_type)));
8966
3/4
✓ Branch 0 taken 7009 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 541 times.
✓ Branch 3 taken 6468 times.
7009 if (part_info->check_partition_info(thd, &engine_type, file.get(),
8967 create_info, false))
8968 541 return true;
8969 6468 part_info->default_engine_type = engine_type;
8970
8971
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 6451 times.
6468 if (!engine_type->partition_flags) {
8972 /*
8973 The handler assigned to the table cannot handle partitioning.
8974 */
8975
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "native partitioning");
8976 17 return true;
8977 }
8978
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6448 times.
6451 if (create_info->db_type != engine_type) {
8979 /*
8980 We come here when we don't use a partitioned handler.
8981 Since we use a partitioned table it must be "native partitioned".
8982 We have switched engine from defaults, most likely only specified
8983 engines in partition clauses.
8984 */
8985
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 file.reset(get_new_handler((TABLE_SHARE *)nullptr, true, thd->mem_root,
8986 engine_type));
8987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (file.get() == nullptr) {
8988 mem_alloc_error(sizeof(handler));
8989 return true;
8990 }
8991 3 create_info->db_type = engine_type;
8992 }
8993
5/6
✓ Branch 0 taken 6451 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 6419 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 6448 times.
6483 if (alter_info->has_compressed_columns() &&
8994
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 29 times.
32 !ha_check_storage_engine_flag(part_info->default_engine_type,
8995 HTON_SUPPORTS_COMPRESSED_COLUMNS)) {
8996
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
8997
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ha_resolve_storage_engine_name(part_info->default_engine_type),
8998 "COMPRESSED COLUMNS");
8999 3 return true;
9000 }
9001 }
9002
9003 758809 Table_exists_result ter = check_if_table_exists(
9004 thd, db, table_name, alias,
9005 758809 (create_info->options & HA_LEX_CREATE_TMP_TABLE),
9006
1/2
✓ Branch 0 taken 758812 times.
✗ Branch 1 not taken.
758809 (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS), internal_tmp_table);
9007
2/2
✓ Branch 0 taken 1104 times.
✓ Branch 1 taken 757708 times.
758812 if (ter.m_error) {
9008 1104 return true;
9009 }
9010
2/2
✓ Branch 0 taken 5324 times.
✓ Branch 1 taken 752384 times.
757708 if (ter.m_table_exists) {
9011 5324 return false;
9012 }
9013
9014 /* Suppress key length errors if this is a white listed table. */
9015 752384 Key_length_error_handler error_handler;
9016 bool is_whitelisted_table =
9017 752384 (create_info->options & HA_LEX_CREATE_TMP_TABLE) !=
9018
2/2
✓ Branch 0 taken 658197 times.
✓ Branch 1 taken 41715 times.
699912 HA_LEX_CREATE_TMP_TABLE &&
9019 699912 (thd->is_server_upgrade_thread() ||
9020
4/4
✓ Branch 0 taken 699912 times.
✓ Branch 1 taken 52472 times.
✓ Branch 2 taken 546708 times.
✓ Branch 3 taken 111489 times.
1999004 create_info->db_type->db_type == DB_TYPE_INNODB) &&
9021
8/16
✓ Branch 0 taken 588423 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 588423 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 588423 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 588423 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 182071 times.
✓ Branch 9 taken 406352 times.
✓ Branch 10 taken 588423 times.
✓ Branch 11 taken 163964 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
1340810 (dd::get_dictionary()->is_dd_table_name(db, error_table_name) ||
9022
12/20
✓ Branch 0 taken 182071 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182071 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 182071 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 182071 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 51954 times.
✓ Branch 9 taken 130117 times.
✓ Branch 10 taken 182071 times.
✓ Branch 11 taken 570313 times.
✓ Branch 12 taken 182068 times.
✓ Branch 13 taken 570316 times.
✓ Branch 14 taken 588423 times.
✓ Branch 15 taken 163964 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
934455 dd::get_dictionary()->is_system_table_name(db, error_table_name));
9023
3/4
✓ Branch 0 taken 458306 times.
✓ Branch 1 taken 294081 times.
✓ Branch 2 taken 458306 times.
✗ Branch 3 not taken.
752387 if (is_whitelisted_table) thd->push_internal_handler(&error_handler);
9024
9025
1/2
✓ Branch 0 taken 752382 times.
✗ Branch 1 not taken.
752387 bool prepare_error = mysql_prepare_create_table(
9026 thd, db, error_table_name, create_info, alter_info, file.get(),
9027 (part_info != nullptr), key_info, key_count, fk_key_info, fk_key_count,
9028 existing_fk_info, existing_fk_count, existing_fk_table,
9029 fk_max_generated_name_number, select_field_count, find_parent_keys);
9030
9031
3/4
✓ Branch 0 taken 458306 times.
✓ Branch 1 taken 294076 times.
✓ Branch 2 taken 458306 times.
✗ Branch 3 not taken.
752382 if (is_whitelisted_table) thd->pop_internal_handler();
9032
9033
2/2
✓ Branch 0 taken 8960 times.
✓ Branch 1 taken 743422 times.
752382 if (prepare_error) return true;
9034
9035
1/2
✓ Branch 0 taken 743417 times.
✗ Branch 1 not taken.
743422 THD_STAGE_INFO(thd, stage_creating_table);
9036
9037 {
9038 size_t dirlen;
9039 char dirpath[FN_REFLEN];
9040
9041 /*
9042 data_file_name and index_file_name include the table name without
9043 extension. Mostly this does not refer to an existing file. When
9044 comparing data_file_name or index_file_name against the data
9045 directory, we try to resolve all symbolic links. On some systems,
9046 we use realpath(3) for the resolution. This returns ENOENT if the
9047 resolved path does not refer to an existing file. my_realpath()
9048 does then copy the requested path verbatim, without symlink
9049 resolution. Thereafter the comparison can fail even if the
9050 requested path is within the data directory. E.g. if symlinks to
9051 another file system are used. To make realpath(3) return the
9052 resolved path, we strip the table name and compare the directory
9053 path only. If the directory doesn't exist either, table creation
9054 will fail anyway.
9055 */
9056
2/2
✓ Branch 0 taken 236 times.
✓ Branch 1 taken 743181 times.
743417 if (create_info->data_file_name) {
9057
1/2
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
236 dirname_part(dirpath, create_info->data_file_name, &dirlen);
9058
3/4
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 230 times.
236 if (test_if_data_home_dir(dirpath)) {
9059
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
9060 9 return true;
9061 }
9062 }
9063
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 743386 times.
743411 if (create_info->index_file_name) {
9064
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 dirname_part(dirpath, create_info->index_file_name, &dirlen);
9065
3/4
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 22 times.
25 if (test_if_data_home_dir(dirpath)) {
9066
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
9067 3 return true;
9068 }
9069 }
9070 }
9071
9072
3/4
✓ Branch 0 taken 743398 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 743393 times.
743408 if (check_partition_dirs(thd->lex->part_info)) return true;
9073
9074
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 743385 times.
743393 if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) {
9075
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (create_info->data_file_name)
9076
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 push_warning_printf(thd, Sql_condition::SL_WARNING, WARN_OPTION_IGNORED,
9077 ER_THD(thd, WARN_OPTION_IGNORED), "DATA DIRECTORY");
9078
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (create_info->index_file_name)
9079
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 push_warning_printf(thd, Sql_condition::SL_WARNING, WARN_OPTION_IGNORED,
9080 ER_THD(thd, WARN_OPTION_IGNORED), "INDEX DIRECTORY");
9081 8 create_info->data_file_name = create_info->index_file_name = nullptr;
9082 }
9083
9084
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 743392 times.
743393 if (thd->variables.keep_files_on_create)
9085 1 create_info->options |= HA_CREATE_KEEP_FILES;
9086
9087 /*
9088 Create table definitions.
9089 If "no_ha_table" is false also create table in storage engine.
9090 */
9091
2/2
✓ Branch 0 taken 52459 times.
✓ Branch 1 taken 690934 times.
743393 if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
9092
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 52347 times.
104917 if (rea_create_tmp_table(thd, path, schema, db, table_name, create_info,
9093 52460 alter_info->create_list, *key_count, *key_info,
9094 keys_onoff,
9095
1/2
✓ Branch 0 taken 52458 times.
✗ Branch 1 not taken.
52460 &alter_info->check_constraint_spec_list,
9096 file.get(), no_ha_table, is_trans, table_def))
9097 111 return true;
9098 } else {
9099
2/2
✓ Branch 0 taken 1191 times.
✓ Branch 1 taken 689736 times.
1381861 if (rea_create_base_table(thd, path, schema, db, table_name, create_info,
9100 690940 alter_info->create_list, *key_count, *key_info,
9101 keys_onoff, *fk_key_count, *fk_key_info,
9102
1/2
✓ Branch 0 taken 690927 times.
✗ Branch 1 not taken.
690940 &alter_info->check_constraint_spec_list,
9103 file.get(), no_ha_table, do_not_store_in_dd,
9104 part_info, is_trans, table_def, post_ddl_ht))
9105 1191 return true;
9106 }
9107
9108
1/2
✓ Branch 0 taken 742083 times.
✗ Branch 1 not taken.
742083 THD_STAGE_INFO(thd, stage_after_create);
9109
6/6
✓ Branch 0 taken 52347 times.
✓ Branch 1 taken 689736 times.
✓ Branch 2 taken 2314 times.
✓ Branch 3 taken 50033 times.
✓ Branch 4 taken 2314 times.
✓ Branch 5 taken 739769 times.
794430 if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
9110 52347 thd->in_multi_stmt_transaction_mode()) {
9111 /*
9112 When autocommit is disabled, creating temporary table sets this
9113 flag to start transaction in any case (regardless of binlog=on/off,
9114 binlog format and transactional/non-transactional engine) to make
9115 behavior consistent.
9116 */
9117 2314 thd->server_status |= SERVER_STATUS_IN_TRANS;
9118 }
9119 742083 return false;
9120 759411 }
9121
9122 /*
9123 This function disallows requests to use general tablespace for the table
9124 with ENCRYPTION clause different from the general tablespace's encryption
9125 type.
9126
9127 @param thd Thread
9128 @param create_info Metadata of the table.
9129
9130 @returns true on failure, false on success.
9131 */
9132 707096 static bool validate_table_encryption(THD *thd, HA_CREATE_INFO *create_info) {
9133 // Study if this table uses general tablespaces and if any one is encrypted.
9134 707096 bool uses_general_tablespace = false;
9135 707096 bool uses_encrypted_tablespace = false;
9136 707096 bool uses_system_tablespace = false;
9137 dd::Encrypt_result result =
9138
1/2
✓ Branch 0 taken 707110 times.
✗ Branch 1 not taken.
707096 dd::is_tablespace_encrypted(thd, create_info, &uses_general_tablespace);
9139
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 707104 times.
707110 if (result.error) return true;
9140
9141
2/2
✓ Branch 0 taken 453030 times.
✓ Branch 1 taken 254074 times.
707104 if (uses_general_tablespace) {
9142 453030 uses_encrypted_tablespace = result.value;
9143
2/2
✓ Branch 0 taken 252738 times.
✓ Branch 1 taken 1336 times.
254074 } else if (!create_info->tablespace &&
9144
2/2
✓ Branch 0 taken 133680 times.
✓ Branch 1 taken 119058 times.
252738 create_info->db_type->get_tablespace_type_by_name) {
9145 /*
9146 No tablespace is explicitly specified. InnoDB can either use
9147 file-per-table or general tablespace based on 'innodb_file_per_table'
9148 setting, so ask SE about it.
9149 */
9150 Tablespace_type tt;
9151
2/4
✓ Branch 0 taken 133683 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 133683 times.
133680 if (create_info->db_type->get_tablespace_type_by_name(
9152 create_info->tablespace, &tt)) {
9153 return true;
9154 }
9155
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 133251 times.
134115 uses_general_tablespace = (tt != Tablespace_type::SPACE_TYPE_IMPLICIT &&
9156
1/2
✓ Branch 0 taken 432 times.
✗ Branch 1 not taken.
432 tt != Tablespace_type::SPACE_TYPE_SHARED);
9157 133683 uses_system_tablespace = tt == Tablespace_type::SPACE_TYPE_SYSTEM;
9158
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 133251 times.
133683 if (uses_system_tablespace) {
9159
1/2
✓ Branch 0 taken 432 times.
✗ Branch 1 not taken.
432 dd::Encrypt_result result2 = dd::is_system_tablespace_encrypted(thd);
9160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 432 times.
432 if (result2.error) return true;
9161 432 uses_encrypted_tablespace = result2.value;
9162 }
9163 }
9164
9165 /*
9166 Stop if table's uses general tablespace and the requested encryption
9167 type does not match the general tablespace encryption type.
9168 We allow to create table inside encrypted tablespace when ONLINE_TO_KEYRING
9169 is specified. This table will be created in encrypted tablespace - which we
9170 aim for and can be rotated to Keyring (given encryption threads are ON).
9171 */
9172
1/2
✓ Branch 0 taken 707103 times.
✗ Branch 1 not taken.
707107 bool requested_type = dd::is_encrypted(create_info->encrypt_type);
9173
9174
5/6
✓ Branch 0 taken 253641 times.
✓ Branch 1 taken 453462 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 253641 times.
✓ Branch 4 taken 200 times.
✓ Branch 5 taken 453262 times.
707103 if ((uses_general_tablespace || uses_system_tablespace) &&
9175 200 ((requested_type != uses_encrypted_tablespace) &&
9176
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 174 times.
200 (!uses_encrypted_tablespace ||
9177
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 global_system_variables.default_table_encryption !=
9178 DEFAULT_TABLE_ENC_ONLINE_TO_KEYRING))) {
9179
5/6
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 174 times.
✓ Branch 3 taken 26 times.
✓ Branch 4 taken 200 times.
✗ Branch 5 not taken.
200 my_error(ER_INVALID_ENCRYPTION_REQUEST, MYF(0),
9180 requested_type ? "'encrypted'" : "'unencrypted'",
9181 uses_encrypted_tablespace ? "'encrypted'" : "'unencrypted'");
9182 200 return true;
9183 }
9184
9185 706903 return false;
9186 }
9187
9188 5538587 static void warn_on_deprecated_float_auto_increment(
9189 THD *thd, const Create_field &sql_field) {
9190
2/2
✓ Branch 0 taken 239346 times.
✓ Branch 1 taken 5299241 times.
5538587 if ((sql_field.flags & AUTO_INCREMENT_FLAG) &&
9191
2/2
✓ Branch 0 taken 239339 times.
✓ Branch 1 taken 7 times.
239346 (sql_field.sql_type == MYSQL_TYPE_FLOAT ||
9192
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 239317 times.
239339 sql_field.sql_type == MYSQL_TYPE_DOUBLE)) {
9193 29 push_warning_printf(thd, Sql_condition::SL_WARNING,
9194 ER_WARN_DEPRECATED_FLOAT_AUTO_INCREMENT,
9195 ER_THD(thd, ER_WARN_DEPRECATED_FLOAT_AUTO_INCREMENT),
9196 29 sql_field.field_name);
9197 }
9198 5538587 }
9199
9200 58208 static void warn_on_deprecated_float_precision(THD *thd,
9201 const Create_field &sql_field) {
9202
2/2
✓ Branch 0 taken 41021 times.
✓ Branch 1 taken 17187 times.
58208 if (sql_field.decimals != DECIMAL_NOT_SPECIFIED) {
9203
2/2
✓ Branch 0 taken 41016 times.
✓ Branch 1 taken 5 times.
41021 if (sql_field.sql_type == MYSQL_TYPE_FLOAT ||
9204
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 40959 times.
41016 sql_field.sql_type == MYSQL_TYPE_DOUBLE) {
9205 62 push_warning(thd, Sql_condition::SL_WARNING,
9206 ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT,
9207 ER_THD(thd, ER_WARN_DEPRECATED_FLOAT_DIGITS));
9208 }
9209 }
9210 58208 }
9211
9212 58208 static void warn_on_deprecated_float_unsigned(THD *thd,
9213 const Create_field &sql_field) {
9214
2/2
✓ Branch 0 taken 20684 times.
✓ Branch 1 taken 37524 times.
58208 if ((sql_field.flags & UNSIGNED_FLAG) &&
9215
2/2
✓ Branch 0 taken 20680 times.
✓ Branch 1 taken 4 times.
20684 (sql_field.sql_type == MYSQL_TYPE_FLOAT ||
9216
2/2
✓ Branch 0 taken 20674 times.
✓ Branch 1 taken 6 times.
20680 sql_field.sql_type == MYSQL_TYPE_DOUBLE ||
9217
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 20666 times.
20674 sql_field.sql_type == MYSQL_TYPE_NEWDECIMAL)) {
9218 18 push_warning(thd, Sql_condition::SL_WARNING,
9219 ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT,
9220 ER_THD(thd, ER_WARN_DEPRECATED_FLOAT_UNSIGNED));
9221 }
9222 58208 }
9223
9224 58208 static void warn_on_deprecated_zerofill(THD *thd,
9225 const Create_field &sql_field) {
9226 // The YEAR data type is implicitly ZEROFILL. Should only warn if it has been
9227 // declared explicitly as ZEROFILL, but that cannot be determined at this
9228 // point, so suppress the warning to avoid confusion.
9229
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 58191 times.
58208 if (sql_field.sql_type == MYSQL_TYPE_YEAR) return;
9230
9231
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 58162 times.
58191 if (sql_field.flags & ZEROFILL_FLAG)
9232 29 push_warning(thd, Sql_condition::SL_WARNING,
9233 ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT,
9234 ER_THD(thd, ER_WARN_DEPRECATED_ZEROFILL));
9235 }
9236
9237 /**
9238 Simple wrapper around create_table_impl() to be used
9239 in various version of CREATE TABLE statement.
9240 */
9241 671438 bool mysql_create_table_no_lock(THD *thd, const char *db,
9242 const char *table_name,
9243 HA_CREATE_INFO *create_info,
9244 Alter_info *alter_info, uint select_field_count,
9245 bool find_parent_keys, bool *is_trans,
9246 handlerton **post_ddl_ht) {
9247 KEY *not_used_1;
9248 uint not_used_2;
9249 671438 FOREIGN_KEY *not_used_3 = nullptr;
9250 671438 uint not_used_4 = 0;
9251 671438 std::unique_ptr<dd::Table> not_used_5;
9252 char path[FN_REFLEN + 1];
9253
9254
2/2
✓ Branch 0 taken 51391 times.
✓ Branch 1 taken 620047 times.
671438 if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
9255
1/2
✓ Branch 0 taken 51386 times.
✗ Branch 1 not taken.
51391 build_tmptable_filename(thd, path, sizeof(path));
9256 else {
9257 bool was_truncated;
9258
1/2
✓ Branch 0 taken 620045 times.
✗ Branch 1 not taken.
620047 const char *alias = table_case_name(create_info, table_name);
9259
1/2
✓ Branch 0 taken 620051 times.
✗ Branch 1 not taken.
620045 build_table_filename(path, sizeof(path) - 1 - reg_ext_length, db, alias, "",
9260 0, &was_truncated);
9261 // Check truncation, will lead to overflow when adding extension
9262
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 620050 times.
620051 if (was_truncated) {
9263
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_IDENT_CAUSES_TOO_LONG_PATH, MYF(0), sizeof(path) - 1, path);
9264 1 return true;
9265 }
9266 }
9267
9268 /*
9269 Don't create the DD tables in the DDSE unless installing the DD.
9270 */
9271
9272 671436 bool no_ha_table = false;
9273
14/22
✓ Branch 0 taken 614510 times.
✓ Branch 1 taken 56926 times.
✓ Branch 2 taken 614507 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 614511 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 614515 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 614514 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 393425 times.
✓ Branch 11 taken 221089 times.
✓ Branch 12 taken 614510 times.
✓ Branch 13 taken 56930 times.
✓ Branch 14 taken 614512 times.
✓ Branch 15 taken 56930 times.
✓ Branch 16 taken 393425 times.
✓ Branch 17 taken 278020 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
671436 if (!opt_initialize && dd::get_dictionary()->is_dd_table_name(db, table_name))
9274 393425 no_ha_table = true;
9275
9276 // Check if the schema exists. We must make sure the schema is released
9277 // and unlocked in the right order.
9278 671445 dd::Schema_MDL_locker mdl_locker(thd);
9279
1/2
✓ Branch 0 taken 671441 times.
✗ Branch 1 not taken.
671433 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
9280 671441 const dd::Schema *schema = nullptr;
9281
9/16
✓ Branch 0 taken 671435 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 671438 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 671442 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 671439 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7 times.
✓ Branch 9 taken 671432 times.
✓ Branch 10 taken 671432 times.
✓ Branch 11 taken 4 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 671440 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
671441 if (mdl_locker.ensure_locked(db) || thd->dd_client()->acquire(db, &schema)) {
9282 // Error is reported by the dictionary subsystem.
9283 return true;
9284 }
9285
9286
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 671433 times.
671440 if (schema == nullptr) {
9287
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_error(ER_BAD_DB_ERROR, MYF(0), db);
9288 7 return true;
9289 }
9290
9291 // Fix create_info->explicit_encryption. For alter it is retrieved
9292 // from share.
9293
2/2
✓ Branch 0 taken 671431 times.
✓ Branch 1 taken 2 times.
671433 if (!(create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE) &&
9294
2/2
✓ Branch 0 taken 22131 times.
✓ Branch 1 taken 649300 times.
671431 (create_info->used_fields & HA_CREATE_USED_ENCRYPT)) {
9295 22131 create_info->explicit_encryption = true;
9296 }
9297
9298 // Do not accept AUTOEXTEND_SIZE clauses for
9299 // temporary table.
9300
2/2
✓ Branch 0 taken 51389 times.
✓ Branch 1 taken 620044 times.
671433 if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
9301
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 51388 times.
51389 if (create_info->m_implicit_tablespace_autoextend_size > 0) {
9302
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_CANNOT_USE_AUTOEXTEND_SIZE_CLAUSE, MYF(0), "temporary");
9303 1 return true;
9304 }
9305 }
9306
9307 // Determine table encryption type, and check if user is allowed to create.
9308
2/2
✓ Branch 0 taken 620035 times.
✓ Branch 1 taken 51397 times.
671432 if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
9309 /*
9310 Assume table as encrypted, if user did not explicitly state it and
9311 we have a schema with default encryption enabled.
9312 */
9313
7/8
✓ Branch 0 taken 597142 times.
✓ Branch 1 taken 22893 times.
✓ Branch 2 taken 597142 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 44 times.
✓ Branch 5 taken 597098 times.
✓ Branch 6 taken 44 times.
✓ Branch 7 taken 619991 times.
620035 if (!create_info->encrypt_type.length && schema->default_encryption()) {
9314
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 create_info->encrypt_type = {strmake_root(thd->mem_root, "Y", 1), 1};
9315 }
9316
9317 // Stop if it is invalid encryption clause, when using general tablespace.
9318
3/4
✓ Branch 0 taken 620035 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 105 times.
✓ Branch 3 taken 619930 times.
620035 if (validate_table_encryption(thd, create_info)) return true;
9319
9320 // Check table encryption privilege
9321
4/4
✓ Branch 0 taken 597088 times.
✓ Branch 1 taken 22842 times.
✓ Branch 2 taken 407378 times.
✓ Branch 3 taken 189710 times.
619930 if (create_info->encrypt_type.str || create_info->tablespace) {
9322 /*
9323 Check privilege only if request encryption type differ from schema
9324 default encryption type.
9325 */
9326
1/2
✓ Branch 0 taken 430227 times.
✗ Branch 1 not taken.
430220 bool request_type = dd::is_encrypted(create_info->encrypt_type);
9327
3/4
✓ Branch 0 taken 430216 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5691 times.
✓ Branch 3 taken 424525 times.
430227 if (schema->default_encryption() != request_type) {
9328
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 5656 times.
5691 if (opt_table_encryption_privilege_check) {
9329
3/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 16 times.
35 if (check_table_encryption_admin_access(thd)) {
9330
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 my_error(ER_CANNOT_SET_TABLE_ENCRYPTION, MYF(0));
9331 19 return true;
9332 }
9333
6/8
✓ Branch 0 taken 5656 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326 times.
✓ Branch 3 taken 5330 times.
✓ Branch 4 taken 326 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 326 times.
✓ Branch 7 taken 5330 times.
5656 } else if (schema->default_encryption() && !request_type) {
9334
2/4
✓ Branch 0 taken 326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326 times.
✗ Branch 3 not taken.
326 push_warning(thd, Sql_condition::SL_WARNING,
9335 WARN_UNENCRYPTED_TABLE_IN_ENCRYPTED_DB,
9336 ER_THD(thd, WARN_UNENCRYPTED_TABLE_IN_ENCRYPTED_DB));
9337 }
9338 }
9339 }
9340 }
9341
9342
5/8
✓ Branch 0 taken 671297 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 671307 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6148823 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5477513 times.
✓ Branch 7 taken 671310 times.
6148815 for (const Create_field &sql_field : alter_info->create_list) {
9343
1/2
✓ Branch 0 taken 5477511 times.
✗ Branch 1 not taken.
5477513 warn_on_deprecated_float_auto_increment(thd, sql_field);
9344 }
9345
9346 // Only needed for CREATE TABLE LIKE / SELECT, as warnings for
9347 // pure CREATE TABLE is reported in the parser.
9348
3/4
✓ Branch 0 taken 671307 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9163 times.
✓ Branch 3 taken 662144 times.
671310 if (!thd->lex->query_block->field_list_is_empty()) {
9349
5/8
✓ Branch 0 taken 9163 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9163 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 63584 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 54421 times.
✓ Branch 7 taken 9163 times.
63584 for (const Create_field &sql_field : alter_info->create_list) {
9350
1/2
✓ Branch 0 taken 54421 times.
✗ Branch 1 not taken.
54421 warn_on_deprecated_float_precision(thd, sql_field);
9351
1/2
✓ Branch 0 taken 54421 times.
✗ Branch 1 not taken.
54421 warn_on_deprecated_float_unsigned(thd, sql_field);
9352
1/2
✓ Branch 0 taken 54421 times.
✗ Branch 1 not taken.
54421 warn_on_deprecated_zerofill(thd, sql_field);
9353 }
9354 }
9355
9356
2/2
✓ Branch 0 taken 17307 times.
✓ Branch 1 taken 654002 times.
671307 if (thd->is_plugin_fake_ddl()) no_ha_table = true;
9357
9358
1/2
✓ Branch 0 taken 671285 times.
✗ Branch 1 not taken.
671309 return create_table_impl(
9359 thd, *schema, db, table_name, table_name, path, create_info, alter_info,
9360 false, select_field_count, find_parent_keys, no_ha_table, false, is_trans,
9361 &not_used_1, &not_used_2, Alter_info::ENABLE, &not_used_3, &not_used_4,
9362 671285 nullptr, 0, nullptr, 0, &not_used_5, post_ddl_ht);
9363 671418 }
9364
9365 typedef std::set<std::pair<dd::String_type, dd::String_type>>
9366 Normalized_fk_children;
9367
9368 /**
9369 Fetch names of all tables having a FK referring to the given table.
9370
9371 @param thd Thread handle.
9372 @param parent_schema Schema name of the referenced table.
9373 @param parent_name Name of the referenced table.
9374 @param parent_engine Name of the referenced table's storage engine.
9375 @param [out] fk_children Set of unique schema qualified names of
9376 tables referring the given parent.
9377
9378 The children are fetched from the DD tables using uncommitted read. The
9379 names are normalized, i.e., if l_c_t_n == 2, the names are lowercased.
9380
9381 @retval operation outcome, false if no error.
9382 */
9383
9384 290998 static bool fetch_fk_children_uncached_uncommitted_normalized(
9385 THD *thd, const char *parent_schema, const char *parent_name,
9386 const char *parent_engine, Normalized_fk_children *fk_children) {
9387 290998 std::vector<dd::String_type> children_dbs, children_names;
9388
9389
5/10
✓ Branch 0 taken 290996 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 291009 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 291008 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 291007 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 291010 times.
291008 if (thd->dd_client()->fetch_fk_children_uncached(
9390 parent_schema, parent_name, parent_engine, true, &children_dbs,
9391 &children_names))
9392 return true;
9393
9394 291010 auto db_it = children_dbs.begin();
9395 291008 auto names_it = children_names.begin();
9396
9397
2/2
✓ Branch 0 taken 1858 times.
✓ Branch 1 taken 291008 times.
292867 while (db_it != children_dbs.end()) {
9398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1858 times.
1858 assert(names_it != children_names.end());
9399 char buff_db[NAME_LEN + 1];
9400 char buff_table[NAME_LEN + 1];
9401 1858 my_stpncpy(buff_db, db_it->c_str(), NAME_LEN);
9402 1858 my_stpncpy(buff_table, names_it->c_str(), NAME_LEN);
9403 /*
9404 In lower-case-table-names == 2 mode we store original versions of table
9405 and db names in the data-dictionary. Hence they need to be lowercased
9406 to produce correct MDL key for them and for other uses.
9407 */
9408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1858 times.
1858 if (lower_case_table_names == 2) {
9409 my_casedn_str(system_charset_info, buff_db);
9410 my_casedn_str(system_charset_info, buff_table);
9411 }
9412
9413
1/2
✓ Branch 0 taken 1858 times.
✗ Branch 1 not taken.
1858 fk_children->insert(
9414
1/2
✓ Branch 0 taken 1858 times.
✗ Branch 1 not taken.
3716 typename Normalized_fk_children::value_type(buff_db, buff_table));
9415
9416 1858 ++db_it;
9417 1858 ++names_it;
9418 }
9419 291008 return false;
9420 291008 }
9421
9422 114993 bool collect_fk_children(THD *thd, const char *db, const char *arg_table_name,
9423 handlerton *hton, enum_mdl_type lock_type,
9424 MDL_request_list *mdl_requests) {
9425 114993 Normalized_fk_children fk_children;
9426
3/6
✓ Branch 0 taken 115008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 115007 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 115007 times.
115006 if (fetch_fk_children_uncached_uncommitted_normalized(
9427 thd, db, arg_table_name, ha_resolve_storage_engine_name(hton),
9428 &fk_children))
9429 return true;
9430
9431
3/4
✓ Branch 0 taken 731 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 731 times.
✓ Branch 3 taken 115007 times.
115738 for (auto fk_children_it : fk_children) {
9432 731 const char *schema_name = fk_children_it.first.c_str();
9433 731 const char *table_name = fk_children_it.second.c_str();
9434
9435
1/2
✓ Branch 0 taken 731 times.
✗ Branch 1 not taken.
731 MDL_request *mdl_request = new (thd->mem_root) MDL_request;
9436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 731 times.
731 if (mdl_request == nullptr) return true;
9437
9438
1/2
✓ Branch 0 taken 731 times.
✗ Branch 1 not taken.
731 MDL_REQUEST_INIT(mdl_request, MDL_key::TABLE, schema_name, table_name,
9439 lock_type, MDL_STATEMENT);
9440
1/2
✓ Branch 0 taken 731 times.
✗ Branch 1 not taken.
731 mdl_requests->push_front(mdl_request);
9441
9442
1/2
✓ Branch 0 taken 731 times.
✗ Branch 1 not taken.
731 mdl_request = new (thd->mem_root) MDL_request;
9443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 731 times.
731 if (mdl_request == nullptr) return true;
9444
9445
1/2
✓ Branch 0 taken 731 times.
✗ Branch 1 not taken.
731 MDL_REQUEST_INIT(mdl_request, MDL_key::SCHEMA, schema_name, "",
9446 MDL_INTENTION_EXCLUSIVE, MDL_STATEMENT);
9447
9448
1/2
✓ Branch 0 taken 731 times.
✗ Branch 1 not taken.
731 mdl_requests->push_front(mdl_request);
9449
1/2
✓ Branch 0 taken 731 times.
✗ Branch 1 not taken.
731 }
9450 115007 return false;
9451 115007 }
9452
9453 177219 static bool reload_fk_parents_for_single_table(THD *thd, const char *db,
9454 const char *name) {
9455 177219 dd::Table *table = nullptr;
9456
4/8
✓ Branch 0 taken 177219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 177219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 177219 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 177219 times.
177219 if (thd->dd_client()->acquire_for_modification(db, name, &table)) return true;
9457
9458 // Missing parent is allowed for tables created with F_K_C = 0.
9459
2/2
✓ Branch 0 taken 1019 times.
✓ Branch 1 taken 176200 times.
177219 if (table == nullptr) return false;
9460
9461
1/2
✓ Branch 0 taken 176200 times.
✗ Branch 1 not taken.
176200 bool before_image_empty = table->foreign_key_parents().empty();
9462
9463 // Read uncommitted from the DD tables to reload the information.
9464
2/4
✓ Branch 0 taken 176200 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 176200 times.
176200 if (table->reload_foreign_key_parents(thd)) return true;
9465
9466
1/2
✓ Branch 0 taken 176200 times.
✗ Branch 1 not taken.
176200 bool after_image_empty = table->foreign_key_parents().empty();
9467
9468 /*
9469 The changes are reflected in the uncommitted registry in the
9470 dictionary client, which is removed upon rollback. Upon commit,
9471 the corresponding object in the shared cache is invalidated. This
9472 means that there will be an update of the DD tables which is not
9473 necessary, and which also interferes with the use of the
9474 Foreign_key_parents_invalidator.
9475
9476 TODO: In the long term, extend the Dictionary_client to support
9477 caching changes that should not (or will not) be reflected
9478 in the DD tables.
9479
9480 TODO: In the short term, we can improve this to avoid unnecessary
9481 updates if the FK parent collection is unchanged. For now,
9482 skip update if the collection is empty both before and after
9483 reload.
9484 */
9485
4/4
✓ Branch 0 taken 173767 times.
✓ Branch 1 taken 2433 times.
✓ Branch 2 taken 171988 times.
✓ Branch 3 taken 1779 times.
176200 if (before_image_empty && after_image_empty) return false;
9486
9487
1/2
✓ Branch 0 taken 4212 times.
✗ Branch 1 not taken.
4212 return thd->dd_client()->update(table);
9488 }
9489
9490 306290 bool adjust_fk_parents(THD *thd, const char *db, const char *name,
9491 bool reload_self,
9492 const Foreign_key_parents_invalidator *fk_invalidator) {
9493 /*
9494 Can't reload self in case of e.g. DROP. Otherwise, reload the
9495 foreign key parents info in case we e.g. un-orphaned a child.
9496 */
9497
5/8
✓ Branch 0 taken 172599 times.
✓ Branch 1 taken 133691 times.
✓ Branch 2 taken 172599 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 172599 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 306290 times.
306290 if (reload_self && reload_fk_parents_for_single_table(thd, db, name))
9498 return true;
9499
9500 /*
9501 If an invalidator is submitted, use it to decide which tables should
9502 have their FK parent info reloaded. This must be done e.g. for ALTER,
9503 since e.g. the dropped FKs will not be present in the table's FK list
9504 at this point.
9505 */
9506
2/2
✓ Branch 0 taken 60255 times.
✓ Branch 1 taken 246035 times.
306290 if (fk_invalidator != nullptr) {
9507
3/4
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 224 times.
✓ Branch 3 taken 60255 times.
60479 for (auto parent : fk_invalidator->parents()) {
9508 // Self referencing keys should be updated above if reload_self == true.
9509
1/2
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
224 if ((my_strcasecmp(table_alias_charset, parent.first.first.c_str(), db) !=
9510 218 0 ||
9511
2/4
✓ Branch 0 taken 218 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 218 times.
✗ Branch 3 not taken.
218 my_strcasecmp(table_alias_charset, parent.first.second.c_str(),
9512
3/4
✓ Branch 0 taken 218 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 224 times.
448 name) != 0) &&
9513
2/4
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 224 times.
224 reload_fk_parents_for_single_table(thd, parent.first.first.c_str(),
9514 parent.first.second.c_str()))
9515 return true;
9516
1/2
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
224 }
9517 60255 return false;
9518 }
9519
9520 /*
9521 Otherwise, use the FK list in the table and reload FK parent info
9522 for each parent.
9523 */
9524 246035 const dd::Table *table = nullptr;
9525
4/8
✓ Branch 0 taken 246035 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 246035 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 246035 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 246035 times.
246035 if (thd->dd_client()->acquire(db, name, &table)) return true;
9526
9527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 246035 times.
246035 assert(table);
9528
9529
6/10
✓ Branch 0 taken 246035 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 246035 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 246035 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4506 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4506 times.
✓ Branch 9 taken 246035 times.
250541 for (const dd::Foreign_key *fk : table->foreign_keys()) {
9530 // Self referencing keys should be updated above if reload_self == true.
9531
2/4
✓ Branch 0 taken 4506 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4506 times.
✗ Branch 3 not taken.
4506 if ((my_strcasecmp(table_alias_charset,
9532 4482 fk->referenced_table_schema_name().c_str(), db) != 0 ||
9533
4/6
✓ Branch 0 taken 4482 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4482 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4372 times.
✓ Branch 5 taken 110 times.
4482 my_strcasecmp(table_alias_charset, fk->referenced_table_name().c_str(),
9534
3/4
✓ Branch 0 taken 4482 times.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4506 times.
9012 name) != 0) &&
9535
2/4
✓ Branch 0 taken 4396 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4396 times.
4396 reload_fk_parents_for_single_table(
9536
1/2
✓ Branch 0 taken 4396 times.
✗ Branch 1 not taken.
4396 thd, fk->referenced_table_schema_name().c_str(),
9537
1/2
✓ Branch 0 taken 4396 times.
✗ Branch 1 not taken.
4396 fk->referenced_table_name().c_str()))
9538 return true;
9539 }
9540 246035 return false;
9541 }
9542
9543 /**
9544 Check if foreign key's parent table has a column compatible with foreign key's
9545 referenced column.
9546
9547 @param[in] parent_table_def Data-dictionary object for parent table.
9548 @param[in] fk Data-dictionary object for foreign key.
9549 @param[in] fk_el Data-dictionary object for foreign key
9550 element.
9551 @param[in] hton Handlerton for table's storage engine.
9552
9553 @retval false Success.
9554 @retval true Failure.
9555 */
9556 979 static bool check_table_has_col_compatible_with_fk_ref_col(
9557 const dd::Table *parent_table_def, const dd::Foreign_key *fk,
9558 const dd::Foreign_key_element *fk_el, handlerton *hton) {
9559 1041 auto same_column_name = [fk_el](const dd::Column *c) {
9560 1041 return my_strcasecmp(system_charset_info, c->name().c_str(),
9561 1041 fk_el->referenced_column_name().c_str()) == 0;
9562 979 };
9563 auto ref_column =
9564
3/6
✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 979 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 979 times.
✗ Branch 5 not taken.
979 std::find_if(parent_table_def->columns().begin(),
9565
2/4
✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 979 times.
✗ Branch 3 not taken.
979 parent_table_def->columns().end(), same_column_name);
9566
4/6
✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 979 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 978 times.
979 if (ref_column == parent_table_def->columns().end()) {
9567
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_FK_NO_COLUMN_PARENT, MYF(0),
9568
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 fk_el->referenced_column_name().c_str(), fk->name().c_str(),
9569
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 fk->referenced_table_name().c_str());
9570 1 return true;
9571 }
9572
9573
3/6
✓ Branch 0 taken 978 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 978 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 978 times.
978 if ((*ref_column)->is_virtual()) {
9574 my_error(ER_FK_CANNOT_USE_VIRTUAL_COLUMN, MYF(0), fk->name().c_str(),
9575 fk_el->referenced_column_name().c_str());
9576 return true;
9577 }
9578
9579 // Check that type of referencing and referenced columns are compatible.
9580
1/2
✓ Branch 0 taken 978 times.
✗ Branch 1 not taken.
978 if (hton->check_fk_column_compat) {
9581 Ha_fk_column_type child_column_type, parent_column_type;
9582
9583
4/8
✓ Branch 0 taken 978 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 978 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 978 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 978 times.
1956 if (fill_ha_fk_column_type(&child_column_type, &fk_el->column()) ||
9584
3/6
✓ Branch 0 taken 978 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 978 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 978 times.
978 fill_ha_fk_column_type(&parent_column_type, *ref_column))
9585 9 return true;
9586
9587
3/4
✓ Branch 0 taken 978 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 969 times.
978 if (!hton->check_fk_column_compat(&child_column_type, &parent_column_type,
9588 true)) {
9589
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_error(ER_FK_INCOMPATIBLE_COLUMNS, MYF(0),
9590
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 fk_el->column().name().c_str(),
9591
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 fk_el->referenced_column_name().c_str(), fk->name().c_str());
9592 9 return true;
9593 }
9594 }
9595
9596 969 return false;
9597 }
9598
9599 /**
9600 Check if new definition of parent table is compatible with foreign keys
9601 on child table which reference it. Update the unique constraint names and
9602 referenced column names for the foreign keys accordingly.
9603
9604 @param thd Thread handle.
9605 @param check_only Indicates that we only need to check parent key
9606 existence and do not do real update.
9607 @param check_charsets Indicates whether we need to check charsets of
9608 columns participating in foreign keys.
9609 @param child_table_db Child table schema name.
9610 @param child_table_name Child table name.
9611 @param parent_table_db Parent table schema name.
9612 @param parent_table_name Parent table name.
9613 @param hton Handlerton for tables' storage engine.
9614 @param parent_table_def Table object representing the new version of
9615 referenced table.
9616 @param parent_alter_info Alter_info containing information about renames
9617 of parent columns. Can be nullptr if there are
9618 no such renames.
9619 @param old_parent_table_def Table object representing the old version of
9620 referenced table. Can be nullptr if this is
9621 not ALTER TABLE. Used for error reporting.
9622
9623 @retval operation outcome, false if no error.
9624 */
9625 1126 static bool adjust_fk_child_after_parent_def_change(
9626 THD *thd, bool check_only, bool check_charsets, const char *child_table_db,
9627 const char *child_table_name, const char *parent_table_db,
9628 const char *parent_table_name, handlerton *hton,
9629 const dd::Table *parent_table_def, Alter_info *parent_alter_info,
9630 const dd::Table *old_parent_table_def) {
9631
1/2
✓ Branch 0 taken 1126 times.
✗ Branch 1 not taken.
1126 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
9632
9633 1126 dd::Table *child_table_def = nullptr;
9634 1126 const dd::Table *old_child_table_def = nullptr;
9635
9636
4/8
✓ Branch 0 taken 1126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1126 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1126 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1126 times.
1126 if (thd->dd_client()->acquire_for_modification(
9637 child_table_db, child_table_name, &child_table_def))
9638 return true;
9639
9640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1126 times.
1126 if (child_table_def == nullptr) {
9641 // Safety.
9642 return false;
9643 }
9644
9645 /*
9646 Check if we are making parent table in a foreign key (possibly
9647 previously orphan) a partitioned table and table's storage engine
9648 doesn't support foreign keys over partitioned tables.
9649 */
9650
5/6
✓ Branch 0 taken 1126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1125 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1125 times.
1127 if (parent_table_def->partition_type() != dd::Table::PT_NONE &&
9651
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 (!hton->partition_flags ||
9652
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 hton->partition_flags() & HA_CANNOT_PARTITION_FK)) {
9653
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_FOREIGN_KEY_ON_PARTITIONED, MYF(0));
9654 1 return true;
9655 }
9656
9657
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 1025 times.
1225 if (old_parent_table_def != nullptr &&
9658
9/18
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 100 times.
✓ Branch 8 taken 100 times.
✓ Branch 9 taken 1025 times.
✓ Branch 10 taken 100 times.
✓ Branch 11 taken 1025 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1125 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
1225 thd->dd_client()->acquire(child_table_db, child_table_name,
9659 &old_child_table_def))
9660 return true;
9661
9662
3/4
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 1025 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 100 times.
1125 assert(old_parent_table_def == nullptr || old_child_table_def != nullptr);
9663
9664
6/10
✓ Branch 0 taken 1125 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1125 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1125 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2414 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2414 times.
✓ Branch 9 taken 1103 times.
3517 for (dd::Foreign_key *fk : *(child_table_def->foreign_keys())) {
9665
2/4
✓ Branch 0 taken 2414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2414 times.
✗ Branch 3 not taken.
2414 if (my_strcasecmp(table_alias_charset,
9666 fk->referenced_table_schema_name().c_str(),
9667
3/4
✓ Branch 0 taken 2414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1127 times.
✓ Branch 3 taken 1287 times.
4828 parent_table_db) == 0 &&
9668
4/6
✓ Branch 0 taken 2414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2414 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1127 times.
✓ Branch 5 taken 1287 times.
2414 my_strcasecmp(table_alias_charset, fk->referenced_table_name().c_str(),
9669 parent_table_name) == 0) {
9670
6/10
✓ Branch 0 taken 1127 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1127 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1127 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1167 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1167 times.
✓ Branch 9 taken 1113 times.
2280 for (dd::Foreign_key_element *fk_el : *(fk->elements())) {
9671
2/2
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 977 times.
1167 if (parent_alter_info) {
9672 /*
9673 The parent table is ALTERed. Check that referenced column was
9674 not dropped and update foreign key definition with its new
9675 name if it was renamed. The latter needs to be done before
9676 searching for parent key.
9677 */
9678
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 List_iterator<Create_field> find_it(parent_alter_info->create_list);
9679 const Create_field *find;
9680
9681
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 88 times.
190 if (check_only) {
9682 /*
9683 This is early stage of ALTER TABLE, so Alter_info::create_list is
9684 fully available and we can use it both to check that column exists
9685 and to handle column renames.
9686 */
9687
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 2 times.
139 while ((find = find_it++)) {
9688
3/4
✓ Branch 0 taken 137 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 100 times.
✓ Branch 3 taken 37 times.
274 if (find->field &&
9689
4/6
✓ Branch 0 taken 137 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 137 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 100 times.
✓ Branch 5 taken 37 times.
137 my_strcasecmp(system_charset_info,
9690 fk_el->referenced_column_name().c_str(),
9691 find->field->field_name) == 0) {
9692 100 break;
9693 }
9694 }
9695
9696
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 100 times.
102 if (find == nullptr) {
9697
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_FK_COLUMN_CANNOT_DROP_CHILD, MYF(0),
9698
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 fk_el->referenced_column_name().c_str(),
9699
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 fk->name().c_str(), fk->table().name().c_str());
9700 4 return true;
9701 }
9702
9703 /*
9704 Column can't be made virtual as we don't allow ALTERs which make
9705 stored columns virtual.
9706 */
9707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 assert(!find->is_virtual_gcol());
9708
9709 // Use new column name in foreign key definition if name was
9710 // changed.
9711
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 74 times.
100 if (find->change != nullptr) {
9712
2/4
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
26 fk_el->referenced_column_name(find->field_name);
9713 }
9714
9715 /*
9716 Check that types of child and parent columns are compatible.
9717 */
9718
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 if (hton->check_fk_column_compat) {
9719 Ha_fk_column_type child_column_type, parent_column_type;
9720
9721
3/6
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 100 times.
100 if (fill_ha_fk_column_type(&child_column_type, &fk_el->column()))
9722 2 return true;
9723
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 fill_ha_fk_column_type(&parent_column_type, find);
9724
9725
3/4
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 98 times.
100 if (!hton->check_fk_column_compat(&child_column_type,
9726 &parent_column_type,
9727 check_charsets)) {
9728
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_FK_INCOMPATIBLE_COLUMNS, MYF(0),
9729
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 fk_el->column().name().c_str(),
9730
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 fk_el->referenced_column_name().c_str(),
9731
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 fk->name().c_str());
9732 2 return true;
9733 }
9734 }
9735 } else {
9736 /*
9737 This is late stage of ALTER TABLE. Some elements in
9738 Alter_info::create_list are not fully valid. However,
9739 those which are related to renaming of columns are,
9740 so we can use them to update foreign key definitions.
9741 Luckily, thanks to check at early stage of ALTER TABLE
9742 we don't need to do anything else here.
9743 */
9744
2/2
✓ Branch 0 taken 279 times.
✓ Branch 1 taken 65 times.
344 while ((find = find_it++)) {
9745
4/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 253 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 256 times.
305 if (find->change &&
9746
4/6
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 23 times.
✓ Branch 5 taken 3 times.
26 my_strcasecmp(system_charset_info,
9747 fk_el->referenced_column_name().c_str(),
9748 find->change) == 0) {
9749
2/4
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
23 fk_el->referenced_column_name(find->field_name);
9750 23 break;
9751 }
9752 }
9753 }
9754 } else {
9755 /*
9756 We add parent table for previously orphan foreign key by doing
9757 CREATE or RENAME TABLE. We need to check that it has columns
9758 which match referenced columns in foreign key.
9759 */
9760
3/4
✓ Branch 0 taken 977 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 967 times.
977 if (check_table_has_col_compatible_with_fk_ref_col(parent_table_def,
9761 fk, fk_el, hton))
9762 10 return true;
9763 }
9764 }
9765
9766 /*
9767 This function is never, and should never be, called for self referencing
9768 foreign keys. Hence, we can submit 'false' for 'is_self_referenceing_fk'
9769 in the call to prepare_fk_parent_key().
9770 */
9771
6/12
✓ Branch 0 taken 1113 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1113 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1113 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1113 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1113 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1113 times.
1113 assert(my_strcasecmp(table_alias_charset,
9772 fk->referenced_table_schema_name().c_str(),
9773 child_table_db) ||
9774 my_strcasecmp(table_alias_charset,
9775 fk->referenced_table_name().c_str(),
9776 child_table_name));
9777
9778
3/4
✓ Branch 0 taken 1113 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1105 times.
1113 if (prepare_fk_parent_key(hton, parent_table_def, old_parent_table_def,
9779 old_child_table_def, false, fk))
9780 8 return true;
9781 }
9782 }
9783
9784
5/8
✓ Branch 0 taken 1009 times.
✓ Branch 1 taken 94 times.
✓ Branch 2 taken 1009 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1009 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1103 times.
1103 if (!check_only && thd->dd_client()->update(child_table_def)) return true;
9785
9786 1103 return false;
9787 1126 }
9788
9789 172871 bool adjust_fk_children_after_parent_def_change(
9790 THD *thd, bool check_charsets, const char *parent_table_db,
9791 const char *parent_table_name, handlerton *hton,
9792 const dd::Table *parent_table_def, Alter_info *parent_alter_info,
9793 bool invalidate_tdc) {
9794 172871 Normalized_fk_children fk_children;
9795
3/6
✓ Branch 0 taken 172871 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 172871 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 172871 times.
172871 if (fetch_fk_children_uncached_uncommitted_normalized(
9796 thd, parent_table_db, parent_table_name,
9797 ha_resolve_storage_engine_name(hton), &fk_children))
9798 return true;
9799
9800
3/4
✓ Branch 0 taken 1104 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1104 times.
✓ Branch 3 taken 172864 times.
173968 for (auto fk_children_it : fk_children) {
9801 1104 const char *schema_name = fk_children_it.first.c_str();
9802 1104 const char *table_name = fk_children_it.second.c_str();
9803
9804
4/6
✓ Branch 0 taken 1104 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1104 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 88 times.
✓ Branch 5 taken 1016 times.
2208 if (my_strcasecmp(table_alias_charset, schema_name, parent_table_db) == 0 &&
9805
3/4
✓ Branch 0 taken 1104 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
✓ Branch 3 taken 1016 times.
1104 my_strcasecmp(table_alias_charset, table_name, parent_table_name) ==
9806 0) {
9807 // Safety. Self-referencing foreign keys are handled earlier.
9808 88 continue;
9809 }
9810
9811 /*
9812 Since we always pass nullptr as old parent table definition pointer
9813 to the below call, the error message reported by it might be not the
9814 best one for the case when we call this function for ALTER TABLE
9815 which drops parent key. But this does not matter as such errors
9816 should have been normally detected and reported by earlier call
9817 to check_fk_children_after_parent_def_change().
9818 */
9819
3/4
✓ Branch 0 taken 1016 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1009 times.
1016 if (adjust_fk_child_after_parent_def_change(
9820 thd, false /* Update FKs. */, check_charsets, schema_name,
9821 table_name, parent_table_db, parent_table_name, hton,
9822 parent_table_def, parent_alter_info, nullptr))
9823 7 return true;
9824
9825
2/2
✓ Branch 0 taken 793 times.
✓ Branch 1 taken 216 times.
1009 if (invalidate_tdc) {
9826
1/2
✓ Branch 0 taken 793 times.
✗ Branch 1 not taken.
793 mysql_ha_flush_table(thd, schema_name, table_name);
9827
1/2
✓ Branch 0 taken 793 times.
✗ Branch 1 not taken.
793 close_all_tables_for_name(thd, schema_name, table_name, false);
9828 }
9829
9830 #ifdef DISABLED_UNTIL_WL9533
9831 /*
9832 TODO: Simply removing entries from InnoDB internal cache breaks
9833 its FK checking logic at the moment. This is to be solved
9834 as part of WL#9533. We might have to replace invalidation
9835 with cache update to do this.Also we might have to postpone
9836 such invalidation/update until statement commit time.
9837 */
9838 if (hton->dict_cache_reset) hton->dict_cache_reset(schema_name, table_name);
9839 #endif
9840
3/3
✓ Branch 0 taken 1009 times.
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 7 times.
1104 }
9841
9842 172864 return false;
9843 172871 }
9844
9845 /**
9846 Check if new definition of parent table is compatible with foreign keys which
9847 reference it.
9848
9849 @param thd Thread handle.
9850 @param parent_table_db Parent table schema name.
9851 @param parent_table_name Parent table name.
9852 @param hton Handlerton for tables' storage engine.
9853 @param old_parent_table_def Table object representing the old version of
9854 parent table.
9855 @param new_parent_table_def Table object representing the new version of
9856 parent table.
9857 @param parent_alter_info Alter_info containing information about renames
9858 of parent columns.
9859
9860 @retval operation outcome, false if no error.
9861 */
9862 77062 static bool check_fk_children_after_parent_def_change(
9863 THD *thd, const char *parent_table_db, const char *parent_table_name,
9864 handlerton *hton, const dd::Table *old_parent_table_def,
9865 const dd::Table *new_parent_table_def, Alter_info *parent_alter_info) {
9866 77062 for (const dd::Foreign_key_parent *parent_fk :
9867
3/4
✓ Branch 0 taken 77062 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 77052 times.
154216 old_parent_table_def->foreign_key_parents()) {
9868 // Self-referencing FKs are handled separately.
9869
1/2
✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
102 if (my_strcasecmp(table_alias_charset,
9870 parent_fk->child_schema_name().c_str(),
9871
3/4
✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 101 times.
204 parent_table_db) == 0 &&
9872
3/4
✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 101 times.
102 my_strcasecmp(table_alias_charset,
9873 parent_fk->child_table_name().c_str(),
9874 parent_table_name) == 0)
9875 1 continue;
9876
9877
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 91 times.
303 if (adjust_fk_child_after_parent_def_change(
9878 thd, true, // Check only.
9879 /*
9880 Allow charset discrepancies between child and parent columns
9881 in FOREIGN_KEY_CHECKS=0 mode. This provides a way to change
9882 charset of column which participates in a foreign key without
9883 dropping the latter (Note that in general case there is no way
9884 to change charset of both child and parent columns
9885 simultaneously).
9886 We do not allow creation of same discrepancies when adding
9887 new foreign key using CREATE/ALTER TABLE or adding new parent
9888 for existing orphan foreign key using CREATE/RENAME TABLE.
9889 */
9890
1/2
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
101 !(thd->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS),
9891 101 parent_fk->child_schema_name().c_str(),
9892 101 parent_fk->child_table_name().c_str(), parent_table_db,
9893 parent_table_name, hton, new_parent_table_def, parent_alter_info,
9894 old_parent_table_def))
9895 10 return true;
9896 }
9897
9898 77052 return false;
9899 }
9900
9901 /**
9902 Check if new definition of parent table is compatible with foreign keys which
9903 reference it and were previously orphan.
9904
9905 @param thd Thread handle.
9906 @param parent_table_db Parent table schema name.
9907 @param parent_table_name Parent table name.
9908 @param old_parent_table_db Old parent table schema name, if table is
9909 renamed.
9910 @param old_parent_table_name Old parent table name, if table is renamed.
9911 @param hton Handlerton for table's storage engine.
9912 @param parent_table_def Table object representing the parent table.
9913
9914 @retval operation outcome, false if no error.
9915 */
9916 1093 static bool check_fk_children_after_parent_def_change(
9917 THD *thd, const char *parent_table_db, const char *parent_table_name,
9918 const char *old_parent_table_db, const char *old_parent_table_name,
9919 handlerton *hton, const dd::Table *parent_table_def) {
9920 1093 Normalized_fk_children fk_children;
9921
3/6
✓ Branch 0 taken 1093 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1093 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1093 times.
1093 if (fetch_fk_children_uncached_uncommitted_normalized(
9922 thd, parent_table_db, parent_table_name,
9923 ha_resolve_storage_engine_name(hton), &fk_children))
9924 return true;
9925
9926
3/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 1087 times.
1096 for (auto fk_children_it : fk_children) {
9927 9 const char *schema_name = fk_children_it.first.c_str();
9928 9 const char *table_name = fk_children_it.second.c_str();
9929
9930
3/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
18 if (my_strcasecmp(table_alias_charset, schema_name, parent_table_db) == 0 &&
9931
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 my_strcasecmp(table_alias_charset, table_name, parent_table_name) ==
9932 0) {
9933 // Safety. Self-referencing FKs are handled separately.
9934 continue;
9935 }
9936
9937
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (old_parent_table_name != nullptr) {
9938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(old_parent_table_db != nullptr);
9939
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (my_strcasecmp(table_alias_charset, schema_name,
9940
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
4 old_parent_table_db) == 0 &&
9941
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 my_strcasecmp(table_alias_charset, table_name,
9942 old_parent_table_name) == 0) {
9943 /*
9944 In case of ALTER TABLE with RENAME clause, the above check involving
9945 parent_table_db and parent_table_name will skip orphan FKs which
9946 will become non-orphan/adopted self-referencing FKs as result of this
9947 RENAME. Hence we need to do additional check using old_parent_table_db
9948 and old_parent_table_name for non-orphan/adopted self-referencing FKs.
9949 */
9950 continue;
9951 }
9952 }
9953
9954
3/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 3 times.
9 if (adjust_fk_child_after_parent_def_change(
9955 thd, true, // Check only.
9956 true, // Check that charsets match.
9957 schema_name, table_name, parent_table_db, parent_table_name, hton,
9958 parent_table_def, nullptr, nullptr))
9959 6 return true;
9960
2/3
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
9 }
9961 1087 return false;
9962 1093 }
9963
9964 /**
9965 Update the referenced schema- and/or table name for the referencing tables
9966 when the referenced table is renamed.
9967
9968 @param thd Thread handle.
9969 @param parent_table_db Old schema name.
9970 @param parent_table_name Old table name.
9971 @param hton Handlerton for table's storage engine.
9972 @param new_db New schema name.
9973 @param new_table_name New table name.
9974
9975 @retval operation outcome, false if no error.
9976 */
9977 2036 static bool adjust_fk_children_after_parent_rename(
9978 THD *thd, const char *parent_table_db, const char *parent_table_name,
9979 handlerton *hton, const char *new_db, const char *new_table_name) {
9980 2036 Normalized_fk_children fk_children;
9981
3/6
✓ Branch 0 taken 2036 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2036 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2036 times.
2036 if (fetch_fk_children_uncached_uncommitted_normalized(
9982 thd, parent_table_db, parent_table_name,
9983 ha_resolve_storage_engine_name(hton), &fk_children))
9984 return true;
9985
9986
3/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 2036 times.
2047 for (auto fk_children_it : fk_children) {
9987 11 const char *schema_name = fk_children_it.first.c_str();
9988 11 const char *table_name = fk_children_it.second.c_str();
9989
9990
3/6
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
22 if (my_strcasecmp(table_alias_charset, schema_name, parent_table_db) == 0 &&
9991
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 my_strcasecmp(table_alias_charset, table_name, parent_table_name) ==
9992 0) {
9993 continue;
9994 }
9995
9996 11 dd::Table *child_table_def = nullptr;
9997
9998
4/8
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
11 if (thd->dd_client()->acquire_for_modification(schema_name, table_name,
9999 &child_table_def))
10000 return true;
10001
10002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 assert(child_table_def != nullptr);
10003
10004
6/10
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 17 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 17 times.
✓ Branch 9 taken 11 times.
28 for (dd::Foreign_key *fk : *(child_table_def->foreign_keys())) {
10005
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
17 if (my_strcasecmp(table_alias_charset,
10006 fk->referenced_table_schema_name().c_str(),
10007
3/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 6 times.
34 parent_table_db) == 0 &&
10008
4/6
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 6 times.
17 my_strcasecmp(table_alias_charset,
10009 fk->referenced_table_name().c_str(),
10010 parent_table_name) == 0) {
10011
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
11 fk->set_referenced_table_schema_name(new_db);
10012
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
11 fk->set_referenced_table_name(new_table_name);
10013 }
10014 }
10015
10016
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
11 if (thd->dd_client()->update(child_table_def)) return true;
10017
10018
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 mysql_ha_flush_table(thd, schema_name, table_name);
10019
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 close_all_tables_for_name(thd, schema_name, table_name, false);
10020
10021 #ifdef DISABLED_UNTIL_WL9533
10022 /*
10023 TODO: Simply removing entries from InnoDB internal cache breaks
10024 its FK checking logic at the moment. This is to be solved
10025 as part of WL#9533. We might have to replace invalidation
10026 with cache update to do this.Also we might have to postpone
10027 such invalidation/update until statement commit time.
10028 */
10029 if (hton->dict_cache_reset) hton->dict_cache_reset(schema_name, table_name);
10030 #endif
10031
1/3
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
11 }
10032
10033 2036 return false;
10034 2036 }
10035
10036 706289 bool collect_fk_parents_for_new_fks(
10037 THD *thd, const char *db_name, const char *table_name,
10038 const Alter_info *alter_info, enum_mdl_type lock_type, handlerton *hton,
10039 MDL_request_list *mdl_requests,
10040 Foreign_key_parents_invalidator *fk_invalidator) {
10041
2/2
✓ Branch 0 taken 2618695 times.
✓ Branch 1 taken 706289 times.
3324984 for (const Key_spec *key : alter_info->key_list) {
10042
2/2
✓ Branch 0 taken 613139 times.
✓ Branch 1 taken 2005556 times.
2618695 if (key->type == KEYTYPE_FOREIGN) {
10043 613139 const Foreign_key_spec *fk = down_cast<const Foreign_key_spec *>(key);
10044
10045
4/4
✓ Branch 0 taken 613112 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 12029 times.
✓ Branch 3 taken 601110 times.
1226251 if (my_strcasecmp(table_alias_charset, fk->ref_db.str, db_name) == 0 &&
10046
2/2
✓ Branch 0 taken 12029 times.
✓ Branch 1 taken 601083 times.
613112 my_strcasecmp(table_alias_charset, fk->ref_table.str, table_name) ==
10047 0)
10048 12029 continue;
10049
10050
1/2
✓ Branch 0 taken 601110 times.
✗ Branch 1 not taken.
601110 MDL_request *mdl_request = new (thd->mem_root) MDL_request;
10051
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 601110 times.
601110 if (mdl_request == nullptr) return true;
10052
10053 601110 MDL_REQUEST_INIT(mdl_request, MDL_key::TABLE, fk->ref_db.str,
10054 fk->ref_table.str, lock_type, MDL_STATEMENT);
10055
10056 601110 mdl_requests->push_front(mdl_request);
10057
10058
1/2
✓ Branch 0 taken 601110 times.
✗ Branch 1 not taken.
601110 mdl_request = new (thd->mem_root) MDL_request;
10059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 601110 times.
601110 if (mdl_request == nullptr) return true;
10060
10061 601110 MDL_REQUEST_INIT(mdl_request, MDL_key::SCHEMA, fk->ref_db.str, "",
10062 MDL_INTENTION_EXCLUSIVE, MDL_STATEMENT);
10063
10064 601110 mdl_requests->push_front(mdl_request);
10065
10066
2/2
✓ Branch 0 taken 600766 times.
✓ Branch 1 taken 344 times.
601110 if (fk_invalidator)
10067 600766 fk_invalidator->add(fk->ref_db.str, fk->ref_table.str, hton);
10068 }
10069 }
10070 706289 return false;
10071 }
10072
10073 591893 bool collect_fk_names_for_new_fks(THD *thd, const char *db_name,
10074 const char *table_name,
10075 const Alter_info *alter_info,
10076 handlerton *hton,
10077 uint fk_max_generated_name_number,
10078 MDL_request_list *mdl_requests) {
10079 char table_name_lc[NAME_LEN + 1];
10080
1/2
✓ Branch 0 taken 591896 times.
✗ Branch 1 not taken.
591893 strmake(table_name_lc, table_name, NAME_LEN);
10081 /*
10082 Prepare lowercase version of table name unless it is in lower case
10083 already. It is to be used for producing lowercase version of FK name
10084 for acquiring metadata lock on it.
10085 */
10086
2/2
✓ Branch 0 taken 576876 times.
✓ Branch 1 taken 15020 times.
591896 if (lower_case_table_names == 0)
10087
1/2
✓ Branch 0 taken 576875 times.
✗ Branch 1 not taken.
576876 my_casedn_str(system_charset_info, table_name_lc);
10088
10089
2/2
✓ Branch 0 taken 2579883 times.
✓ Branch 1 taken 591893 times.
3171778 for (size_t i = 0; i < alter_info->key_list.size(); i++) {
10090
1/2
✓ Branch 0 taken 2579883 times.
✗ Branch 1 not taken.
2579883 const Key_spec *key = alter_info->key_list[i];
10091
10092
2/2
✓ Branch 0 taken 612799 times.
✓ Branch 1 taken 1967084 times.
2579883 if (key->type == KEYTYPE_FOREIGN) {
10093 612799 const Foreign_key_spec *fk = down_cast<const Foreign_key_spec *>(key);
10094
10095
2/2
✓ Branch 0 taken 661 times.
✓ Branch 1 taken 612138 times.
612799 if (fk->has_explicit_name) {
10096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 661 times.
661 assert(fk->name.str);
10097 /*
10098 Since foreign key names are case-insensitive we need to lowercase
10099 them before passing to MDL subsystem.
10100 */
10101 char fk_name[NAME_LEN + 1];
10102
1/2
✓ Branch 0 taken 661 times.
✗ Branch 1 not taken.
661 strmake(fk_name, fk->name.str, NAME_LEN);
10103
1/2
✓ Branch 0 taken 661 times.
✗ Branch 1 not taken.
661 my_casedn_str(system_charset_info, fk_name);
10104
10105
1/2
✓ Branch 0 taken 661 times.
✗ Branch 1 not taken.
661 MDL_request *mdl_request = new (thd->mem_root) MDL_request;
10106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 661 times.
661 if (mdl_request == nullptr) return true;
10107
10108
1/2
✓ Branch 0 taken 661 times.
✗ Branch 1 not taken.
661 MDL_REQUEST_INIT(mdl_request, MDL_key::FOREIGN_KEY, db_name, fk_name,
10109 MDL_EXCLUSIVE, MDL_STATEMENT);
10110
1/2
✓ Branch 0 taken 661 times.
✗ Branch 1 not taken.
661 mdl_requests->push_front(mdl_request);
10111 } else {
10112 // The below buffer should be sufficient for any generated name.
10113 char fk_name[NAME_LEN + MAX_FK_NAME_SUFFIX_LENGTH + 10 + 1];
10114
10115 /*
10116 Note that the below code is in sync with generate_fk_name().
10117
10118 Use lower-cased version of table name to generate foreign key
10119 name in lower-case.
10120
10121 Here we truncate generated name if it is too long. This is sufficient
10122 for MDL purposes. Error will be reported later in this case.
10123 */
10124 612138 generate_fk_name(fk_name, sizeof(fk_name), table_name_lc, hton,
10125 &fk_max_generated_name_number);
10126
10127
1/2
✓ Branch 0 taken 612138 times.
✗ Branch 1 not taken.
612138 MDL_request *mdl_request = new (thd->mem_root) MDL_request;
10128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 612138 times.
612138 if (mdl_request == nullptr) return true;
10129
10130
1/2
✓ Branch 0 taken 612138 times.
✗ Branch 1 not taken.
612138 MDL_REQUEST_INIT(mdl_request, MDL_key::FOREIGN_KEY, db_name, fk_name,
10131 MDL_EXCLUSIVE, MDL_STATEMENT);
10132
10133
1/2
✓ Branch 0 taken 612138 times.
✗ Branch 1 not taken.
612138 mdl_requests->push_front(mdl_request);
10134 }
10135 }
10136 }
10137
10138 591893 return false;
10139 }
10140
10141 /**
10142 Implementation of SQLCOM_CREATE_TABLE.
10143
10144 Take the metadata locks (including a shared lock on the affected
10145 schema) and create the table. Is written to be called from
10146 mysql_execute_command(), to which it delegates the common parts
10147 with other commands (i.e. implicit commit before and after,
10148 close of thread tables.
10149 */
10150
10151 661764 bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
10152 HA_CREATE_INFO *create_info, Alter_info *alter_info) {
10153 661764 bool result = false;
10154 661764 bool is_trans = false;
10155 uint not_used;
10156 661764 handlerton *post_ddl_ht = nullptr;
10157 661764 bool is_pk_generated = false;
10158 661764 Foreign_key_parents_invalidator fk_invalidator;
10159
1/2
✓ Branch 0 taken 661763 times.
✗ Branch 1 not taken.
661763 DBUG_TRACE;
10160
10161
1/2
✓ Branch 0 taken 661763 times.
✗ Branch 1 not taken.
661763 handlerton *actual_hton = get_viable_handlerton_for_create(
10162 thd, create_table->table_name, *create_info);
10163
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 661746 times.
661763 if (actual_hton == nullptr) return true;
10164
10165 661746 create_info->db_type = actual_hton;
10166
10167
1/2
✓ Branch 0 taken 661747 times.
✗ Branch 1 not taken.
661746 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
10168
10169
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 661679 times.
661747 if (create_info->m_transactional_ddl) {
10170 /*
10171 Stop if START TRANSACTION is requested on table with engine that
10172 does not support atomic DDL.
10173 */
10174
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 67 times.
68 if (!(create_info->db_type->flags & HTON_SUPPORTS_ATOMIC_DDL)) {
10175
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_NOT_ALLOWED_WITH_START_TRANSACTION, MYF(0),
10176 "with engine that does not support atomic DDL.");
10177 1 result = true;
10178 1 goto end;
10179 }
10180
10181 // Stop if START TRANSACTION is requested when creating temporary table.
10182
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 66 times.
67 if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
10183
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_NOT_ALLOWED_WITH_START_TRANSACTION, MYF(0),
10184 "to create temporary tables.");
10185 1 result = true;
10186 1 goto end;
10187 }
10188 }
10189
10190 /*
10191 Open or obtain "X" MDL lock on the table being created.
10192 To check the existence of table, lock of type "S" is obtained on the table
10193 and then it is upgraded to "X" if table does not exists.
10194 */
10195
5/6
✓ Branch 0 taken 661733 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 661168 times.
✓ Branch 3 taken 565 times.
✓ Branch 4 taken 566 times.
✓ Branch 5 taken 661178 times.
1322924 if (open_tables(thd, &thd->lex->query_tables, &not_used, 0) ||
10196
2/4
✓ Branch 0 taken 661179 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 661179 times.
661168 thd->decide_logging_format(thd->lex->query_tables)) {
10197 566 result = true;
10198 566 goto end;
10199 }
10200
10201 /* Got lock. */
10202
3/4
✓ Branch 0 taken 597396 times.
✓ Branch 1 taken 63780 times.
✓ Branch 2 taken 597401 times.
✗ Branch 3 not taken.
661178 DEBUG_SYNC(thd, "locked_table_name");
10203
10204 /*
10205 Do not acquire metadata locks on tables in FK relationships if
10206 table (or view with the same name) exists. They are not necessary
10207 as we won't perform any lookups on them or update of their metadata
10208 in this case.
10209 */
10210
2/2
✓ Branch 0 taken 654746 times.
✓ Branch 1 taken 13 times.
654768 if (!(create_table->table || create_table->is_view()) &&
10211
6/6
✓ Branch 0 taken 654768 times.
✓ Branch 1 taken 6413 times.
✓ Branch 2 taken 604380 times.
✓ Branch 3 taken 50366 times.
✓ Branch 4 taken 508444 times.
✓ Branch 5 taken 152728 times.
1920320 !(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
10212
2/2
✓ Branch 0 taken 508444 times.
✓ Branch 1 taken 95936 times.
604380 (create_info->db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS)) {
10213 /*
10214 CREATE TABLE fails under LOCK TABLES at open_tables() time if target
10215 table doesn't exist already. So we don't need to handle LOCK TABLES
10216 case here by checking that parent tables for new FKs are properly
10217 locked and there are no orphan child tables for which table being
10218 created will become parent.
10219 */
10220
3/4
✓ Branch 0 taken 508441 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 508449 times.
✗ Branch 3 not taken.
508444 assert(thd->locked_tables_mode != LTM_LOCK_TABLES &&
10221 thd->locked_tables_mode != LTM_PRELOCKED_UNDER_LOCK_TABLES);
10222
10223
1/2
✓ Branch 0 taken 508446 times.
✗ Branch 1 not taken.
508449 MDL_request_list mdl_requests;
10224
10225 1525332 if (collect_fk_parents_for_new_fks(thd, create_table->db,
10226 create_table->table_name, alter_info,
10227 MDL_EXCLUSIVE, create_info->db_type,
10228 1525334 &mdl_requests, &fk_invalidator) ||
10229
8/18
✓ Branch 0 taken 508445 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 508441 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 508445 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 508448 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 102101 times.
✓ Branch 9 taken 406347 times.
✓ Branch 10 taken 508451 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 508451 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
1016885 (!dd::get_dictionary()->is_dd_table_name(create_table->db,
10230 102104 create_table->table_name) &&
10231
3/4
✓ Branch 0 taken 102104 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 102103 times.
✓ Branch 3 taken 1 times.
102101 collect_fk_children(thd, create_table->db, create_table->table_name,
10232 create_info->db_type, MDL_EXCLUSIVE,
10233 508447 &mdl_requests)) ||
10234
2/4
✓ Branch 0 taken 508447 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 508448 times.
✗ Branch 3 not taken.
508450 collect_fk_names_for_new_fks(thd, create_table->db,
10235 create_table->table_name, alter_info,
10236 create_info->db_type,
10237 0, // No pre-existing FKs
10238
4/6
✓ Branch 0 taken 508435 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 508435 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 508449 times.
✓ Branch 5 taken 1 times.
1016896 &mdl_requests) ||
10239
2/2
✓ Branch 0 taken 288801 times.
✓ Branch 1 taken 219649 times.
508448 (!mdl_requests.is_empty() &&
10240
2/4
✓ Branch 0 taken 288801 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 288801 times.
288801 thd->mdl_context.acquire_locks(&mdl_requests,
10241 thd->variables.lock_wait_timeout))) {
10242 result = true;
10243 goto end;
10244 }
10245 }
10246
10247 // Prepare check constraints.
10248
3/4
✓ Branch 0 taken 661179 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 661116 times.
661179 if (prepare_check_constraints_for_create(
10249 thd, create_table->db, create_table->table_name, alter_info)) {
10250 63 result = true;
10251 63 goto end;
10252 }
10253
10254 /*
10255 Promote first timestamp column, when explicit_defaults_for_timestamp
10256 is not set
10257 */
10258
2/2
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 660993 times.
661116 if (!thd->variables.explicit_defaults_for_timestamp)
10259
1/2
✓ Branch 0 taken 123 times.
✗ Branch 1 not taken.
123 promote_first_timestamp_column(&alter_info->create_list);
10260
10261 /*
10262 If mode to generate invisible primary key is active then, generate primary
10263 key for the table.
10264 */
10265
5/6
✓ Branch 0 taken 661112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 661016 times.
✓ Branch 4 taken 83 times.
✓ Branch 5 taken 661029 times.
661212 if (is_generate_invisible_primary_key_mode_active(thd) &&
10266
3/4
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 83 times.
✓ Branch 3 taken 13 times.
96 is_candidate_table_for_invisible_primary_key_generation(create_info,
10267 alter_info)) {
10268
3/4
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 79 times.
83 if (validate_and_generate_invisible_primary_key(thd, alter_info)) {
10269 4 result = true;
10270 4 goto end;
10271 }
10272 79 is_pk_generated = true;
10273 }
10274
10275
1/2
✓ Branch 0 taken 661087 times.
✗ Branch 1 not taken.
661108 result = mysql_create_table_no_lock(
10276 thd, create_table->db, create_table->table_name, create_info, alter_info,
10277 0,
10278 /*
10279 We don't need to find parent keys for
10280 FK constraints if table exists.
10281 */
10282
4/4
✓ Branch 0 taken 654701 times.
✓ Branch 1 taken 6407 times.
✓ Branch 2 taken 654688 times.
✓ Branch 3 taken 13 times.
661108 !(create_table->table || create_table->is_view()), &is_trans,
10283 &post_ddl_ht);
10284
10285 /*
10286 Don't write statement if:
10287 - Table creation has failed
10288 - Row-based logging is used and we are creating a temporary table
10289 Otherwise, the statement shall be binlogged.
10290 */
10291
2/2
✓ Branch 0 taken 657977 times.
✓ Branch 1 taken 3110 times.
661087 if (!result) {
10292 /*
10293 CREATE TEMPORARY TABLE doesn't terminate a transaction. Calling
10294 stmt.mark_created_temp_table() guarantees the transaction can be binlogged
10295 correctly.
10296 */
10297
2/2
✓ Branch 0 taken 50305 times.
✓ Branch 1 taken 607672 times.
657977 if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
10298
1/2
✓ Branch 0 taken 50305 times.
✗ Branch 1 not taken.
50305 thd->get_transaction()->mark_created_temp_table(Transaction_ctx::STMT);
10299
10300
5/6
✓ Branch 0 taken 567715 times.
✓ Branch 1 taken 90262 times.
✓ Branch 2 taken 567715 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 617998 times.
✓ Branch 5 taken 39979 times.
1793407 if (!thd->is_current_stmt_binlog_format_row() ||
10301 567715 (thd->is_current_stmt_binlog_format_row() &&
10302
2/2
✓ Branch 0 taken 527736 times.
✓ Branch 1 taken 39979 times.
567715 !(create_info->options & HA_LEX_CREATE_TMP_TABLE))) {
10303
1/2
✓ Branch 0 taken 617998 times.
✗ Branch 1 not taken.
617998 thd->add_to_binlog_accessed_dbs(create_table->db);
10304
10305 /*
10306 If primary key is generated for a table then we create version of CREATE
10307 TABLE statement which includes generated key and invisible column
10308 definitions in explicit form by calling store_create_info(). This is
10309 necessary to correctly binlog/replicate such statements, as we don't
10310 write to binary log value of @@sql_generate_invisible_primary_key
10311 variable, but rely on logging what really has been done instead.
10312 */
10313
8/8
✓ Branch 0 taken 612691 times.
✓ Branch 1 taken 5307 times.
✓ Branch 2 taken 612687 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 62 times.
✓ Branch 5 taken 612625 times.
✓ Branch 6 taken 62 times.
✓ Branch 7 taken 617936 times.
617998 if ((create_table->table == nullptr && !create_table->is_view()) &&
10314 is_pk_generated) {
10315 /*
10316 Open table to generate CREATE TABLE statement. For non-temporary
10317 table we already have exclusive lock here.
10318 */
10319
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 61 times.
62 if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
10320
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 result = open_temporary_table(thd, create_table);
10321 } else {
10322
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN);
10323
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 result = open_table(thd, create_table, &ot_ctx);
10324
10325 // Play safe, remove uncommitted table share from the cache.
10326
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN, create_table->db,
10327 create_table->table_name, false);
10328 }
10329
10330
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 if (!result) {
10331 char buf[2048];
10332 62 String query(buf, sizeof(buf), system_charset_info);
10333 62 query.length(0);
10334
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 result = store_create_info(thd, create_table, &query, create_info,
10335 true /* show_database */,
10336 false /* SHOW CREATE TABLE */);
10337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 assert(result == 0); // store_create_info() always return 0
10338
10339 // Write generated CREATE TABLE statement to binlog.
10340 62 result =
10341
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 write_bin_log(thd, true, query.ptr(), query.length(), is_trans);
10342
10343 /*
10344 Handle TABLE instance created for the non-temporary table here to
10345 avoid problems on transaction rollback. close_thread_table() at the
10346 end of statement will take care about the TABLE instance created
10347 for the temporary table.
10348 */
10349
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 1 times.
62 if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
10350 /*
10351 close_thread_table() will take care about the TABLE instance we
10352 might have created for the non-temporary table, unless we are
10353 under LOCK TABLES. However, creation of non-temporary table is
10354 not allowed under LOCK TABLES. So we can't get here under LOCK
10355 TABLES.
10356 */
10357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 assert(!thd->locked_tables_mode);
10358
1/2
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
61 close_thread_table(thd, &thd->open_tables);
10359 61 create_table->table = nullptr;
10360 }
10361 62 }
10362 } else {
10363
3/6
✓ Branch 0 taken 617936 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 617936 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 617936 times.
✗ Branch 5 not taken.
617936 result = write_bin_log(thd, true, thd->query().str, thd->query().length,
10364 is_trans);
10365 }
10366 }
10367 }
10368
10369
2/2
✓ Branch 0 taken 50440 times.
✓ Branch 1 taken 610647 times.
661087 if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
10370
8/8
✓ Branch 0 taken 604306 times.
✓ Branch 1 taken 6341 times.
✓ Branch 2 taken 604293 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 602410 times.
✓ Branch 5 taken 1883 times.
✓ Branch 6 taken 506913 times.
✓ Branch 7 taken 103734 times.
1213057 if (!(create_table->table || create_table->is_view()) && !result &&
10371
2/2
✓ Branch 0 taken 506913 times.
✓ Branch 1 taken 95497 times.
602410 (create_info->db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS)) {
10372
6/10
✓ Branch 0 taken 506913 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 506913 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 506913 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 506913 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 100568 times.
✓ Branch 9 taken 406345 times.
506913 if (!dd::get_dictionary()->is_dd_table_name(create_table->db,
10373 create_table->table_name)) {
10374 100568 const dd::Table *new_table = nullptr;
10375
10376
4/8
✓ Branch 0 taken 100568 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 100568 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 100568 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 100568 times.
100568 if (thd->dd_client()->acquire(create_table->db,
10377 create_table->table_name, &new_table))
10378 result = true;
10379 else {
10380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100568 times.
100568 assert(new_table != nullptr);
10381 // Check for usage of prefix key index in PARTITION BY KEY() function.
10382
1/2
✓ Branch 0 taken 100568 times.
✗ Branch 1 not taken.
100568 dd::warn_on_deprecated_prefix_key_partition(thd, create_table->db,
10383 create_table->table_name,
10384 new_table, false);
10385 /*
10386 If we are to support FKs for storage engines which don't support
10387 atomic DDL we need to decide what to do for such SEs in case of
10388 failure to update children definitions and adjust code accordingly.
10389 */
10390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100568 times.
100568 assert(is_trans);
10391
10392
1/2
✓ Branch 0 taken 100568 times.
✗ Branch 1 not taken.
100568 if (adjust_fk_children_after_parent_def_change(
10393 thd, create_table->db, create_table->table_name,
10394
4/4
✓ Branch 0 taken 100565 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 100565 times.
201133 create_info->db_type, new_table, nullptr) ||
10395
2/4
✓ Branch 0 taken 100565 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 100565 times.
100565 adjust_fk_parents(thd, create_table->db, create_table->table_name,
10396 true, nullptr))
10397 3 result = true;
10398 }
10399 }
10400 }
10401
10402 // Update view metadata.
10403
2/2
✓ Branch 0 taken 607667 times.
✓ Branch 1 taken 2980 times.
610647 if (!result) {
10404
1/2
✓ Branch 0 taken 607667 times.
✗ Branch 1 not taken.
607667 Uncommitted_tables_guard uncommitted_tables(thd);
10405
10406
6/6
✓ Branch 0 taken 602411 times.
✓ Branch 1 taken 5256 times.
✓ Branch 2 taken 602407 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 602407 times.
✓ Branch 5 taken 5260 times.
607667 if (!create_table->table && !create_table->is_view())
10407
1/2
✓ Branch 0 taken 602407 times.
✗ Branch 1 not taken.
602407 uncommitted_tables.add_table(create_table);
10408
10409
1/2
✓ Branch 0 taken 607667 times.
✗ Branch 1 not taken.
607667 result = update_referencing_views_metadata(thd, create_table, !is_trans,
10410 &uncommitted_tables);
10411 607667 }
10412
10413 /*
10414 Initialize the create select context with details required to perform
10415 rollback and commit operation after the INSERT's are executed. The
10416 context is freed once transaction is rolled back or committed.
10417
10418 We do it just before transaction commit, so that if there is some
10419 error while creating a table, we can skip this initialization. One
10420 reason to do it this way is that the open_tables() acquires S mdl lock
10421 on table name and then later upgrade lock to X. If there is a error
10422 before the lock upgrade, we would have held S mdl lock, but then
10423 attempt to call tdc_remove_table() would assert during call to
10424 m_transactional_ddl.rollback().
10425 */
10426
4/4
✓ Branch 0 taken 607667 times.
✓ Branch 1 taken 2980 times.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 607604 times.
610647 if (!result && create_info->m_transactional_ddl) {
10427
2/4
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
✗ Branch 3 not taken.
63 thd->m_transactional_ddl.init(create_table->db, create_table->table_name,
10428
1/2
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
63 create_info->db_type);
10429 }
10430
10431 /*
10432 Unless we are executing CREATE TEMPORARY TABLE we need to commit
10433 changes to the data-dictionary, SE and binary log and possibly run
10434 handlerton's post-DDL hook.
10435
10436 Also, ignore implicit commit of transaction if we are processing
10437 transactional DDL.
10438 */
10439
6/6
✓ Branch 0 taken 607667 times.
✓ Branch 1 taken 2980 times.
✓ Branch 2 taken 590360 times.
✓ Branch 3 taken 17307 times.
✓ Branch 4 taken 590360 times.
✓ Branch 5 taken 20287 times.
610647 if (!result && !thd->is_plugin_fake_ddl())
10440
2/4
✓ Branch 0 taken 590360 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 590360 times.
✗ Branch 3 not taken.
1180703 result = trans_commit_stmt(thd) ||
10441
2/2
✓ Branch 0 taken 590297 times.
✓ Branch 1 taken 63 times.
590360 (create_info->m_transactional_ddl ? false
10442
3/4
✓ Branch 0 taken 590280 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 590279 times.
590297 : trans_commit_implicit(thd));
10443
10444
5/6
✓ Branch 0 taken 2981 times.
✓ Branch 1 taken 607649 times.
✓ Branch 2 taken 2981 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2981 times.
✓ Branch 5 taken 607649 times.
610630 if (result && !thd->is_plugin_fake_ddl()) {
10445
1/2
✓ Branch 0 taken 2981 times.
✗ Branch 1 not taken.
2981 trans_rollback_stmt(thd);
10446 /*
10447 Full rollback in case we have THD::transaction_rollback_request
10448 and to synchronize DD state in cache and on disk (as statement
10449 rollback doesn't clear DD cache of modified uncommitted objects).
10450 */
10451
1/2
✓ Branch 0 taken 2981 times.
✗ Branch 1 not taken.
2981 trans_rollback(thd);
10452 }
10453
10454 /*
10455 In case of CREATE TABLE post-DDL hook is mostly relevant for case
10456 when statement is rolled back. In such cases it is responsibility
10457 of this hook to cleanup files which might be left after failed
10458 table creation attempt. Ignore calling post-DDL hoot if we are
10459 processing transactional DDL.
10460 */
10461
4/4
✓ Branch 0 taken 610566 times.
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 114149 times.
✓ Branch 3 taken 496417 times.
610630 if (!create_info->m_transactional_ddl && post_ddl_ht)
10462
1/2
✓ Branch 0 taken 114149 times.
✗ Branch 1 not taken.
114149 post_ddl_ht->post_ddl(thd);
10463
10464
2/2
✓ Branch 0 taken 607650 times.
✓ Branch 1 taken 2980 times.
610630 if (!result) {
10465 /*
10466 Don't try to invalidate on error as it might be caused by
10467 failure to acquire locks needed for invalidation.
10468 */
10469
1/2
✓ Branch 0 taken 607650 times.
✗ Branch 1 not taken.
607650 fk_invalidator.invalidate(thd);
10470 }
10471 }
10472
10473 50440 end:
10474 661705 return result;
10475 661722 }
10476
10477 /*
10478 ** Give the key name after the first field with an optional '_#' after
10479 **/
10480
10481 1930915 static bool check_if_keyname_exists(const char *name, KEY *start, KEY *end) {
10482
2/2
✓ Branch 0 taken 4725575 times.
✓ Branch 1 taken 1844355 times.
6569930 for (KEY *key = start; key != end; key++)
10483
2/2
✓ Branch 0 taken 86560 times.
✓ Branch 1 taken 4639015 times.
4725575 if (!my_strcasecmp(system_charset_info, name, key->name)) return true;
10484 1844355 return false;
10485 }
10486
10487 879810 static const char *make_unique_key_name(const char *field_name, KEY *start,
10488 KEY *end) {
10489 char buff[MAX_FIELD_NAME], *buff_end;
10490
10491
5/6
✓ Branch 0 taken 879810 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 795612 times.
✓ Branch 3 taken 84198 times.
✓ Branch 4 taken 795608 times.
✓ Branch 5 taken 84202 times.
1675422 if (!check_if_keyname_exists(field_name, start, end) &&
10492
3/4
✓ Branch 0 taken 795612 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 795608 times.
✓ Branch 3 taken 4 times.
795612 my_strcasecmp(system_charset_info, field_name, primary_key_name))
10493 795608 return field_name; // Use fieldname
10494
1/2
✓ Branch 0 taken 84202 times.
✗ Branch 1 not taken.
84202 buff_end = strmake(buff, field_name, sizeof(buff) - 4);
10495
10496 /*
10497 Only 3 chars + '\0' left, so need to limit to 2 digit
10498 This is ok as we can't have more than 100 keys anyway
10499 */
10500
1/2
✓ Branch 0 taken 85575 times.
✗ Branch 1 not taken.
85575 for (uint i = 2; i < 100; i++) {
10501 85575 *buff_end = '_';
10502
1/2
✓ Branch 0 taken 85575 times.
✗ Branch 1 not taken.
85575 longlong10_to_str(i, buff_end + 1, 10);
10503
4/6
✓ Branch 0 taken 85575 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84202 times.
✓ Branch 3 taken 1373 times.
✓ Branch 4 taken 84202 times.
✗ Branch 5 not taken.
85575 if (!check_if_keyname_exists(buff, start, end)) return sql_strdup(buff);
10504 }
10505 return "not_specified"; // Should never happen
10506 }
10507
10508 /* Ignore errors related to invalid collation during rename table. */
10509 class Rename_table_error_handler : public Internal_error_handler {
10510 public:
10511 7 bool handle_condition(THD *, uint sql_errno, const char *,
10512 Sql_condition::enum_severity_level *,
10513 const char *) override {
10514
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 return (sql_errno == ER_UNKNOWN_COLLATION ||
10515 7 sql_errno == ER_PLUGIN_IS_NOT_LOADED);
10516 }
10517 };
10518
10519 /****************************************************************************
10520 ** Alter a table definition
10521 ****************************************************************************/
10522
10523 /**
10524 Rename histograms from an old table name to a new table name.
10525
10526 @param thd Thread handle
10527 @param old_schema_name The old schema name
10528 @param old_table_name The old table name
10529 @param new_schema_name The new schema name
10530 @param new_table_name The new table name
10531
10532 @return false on success, true on error
10533 */
10534 2404 static bool rename_histograms(THD *thd, const char *old_schema_name,
10535 const char *old_table_name,
10536 const char *new_schema_name,
10537 const char *new_table_name) {
10538 2404 histograms::results_map results;
10539 bool res =
10540
1/2
✓ Branch 0 taken 2404 times.
✗ Branch 1 not taken.
2404 histograms::rename_histograms(thd, old_schema_name, old_table_name,
10541 new_schema_name, new_table_name, results);
10542
10543
4/6
✓ Branch 0 taken 2404 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2403 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2404 DBUG_EXECUTE_IF("fail_after_rename_histograms", {
10544 my_error(ER_UNABLE_TO_UPDATE_COLUMN_STATISTICS, MYF(0), "dummy_column",
10545 old_schema_name, old_table_name);
10546 res = true;
10547 });
10548 2404 return res;
10549 2404 }
10550
10551 /**
10552 Drop histograms from a given table.
10553
10554 This function will check if an ALTER TABLE statement will make a histogram
10555 invalid:
10556 - Removing columns
10557 - Changing columns (data type, collation and such)
10558 - Adding UNIQUE index
10559
10560 If such change is found, remove any existing histogram for these columns.
10561
10562 @param thd thread handler
10563 @param table the table given in ALTER TABLE
10564 @param alter_info the alter changes to be carried out by ALTER TABLE
10565 @param create_info the alter changes to be carried out by ALTER TABLE
10566 @param columns a list of columns to be changed or dropped
10567 @param original_table_def the table definition, pre altering. Note that the
10568 name returned by original_table_def->name() might
10569 not be the same as table->table_name, since this may
10570 be a backup table object with an auto-generated name
10571 @param altered_table_def the table definition, post altering
10572
10573 @return false on success, true on error
10574 */
10575 75389 static bool alter_table_drop_histograms(THD *thd, TABLE_LIST *table,
10576 Alter_info *alter_info,
10577 HA_CREATE_INFO *create_info,
10578 histograms::columns_set &columns,
10579 const dd::Table *original_table_def,
10580 const dd::Table *altered_table_def) {
10581 75389 bool alter_drop_column =
10582 75389 (alter_info->flags &
10583 (Alter_info::ALTER_DROP_COLUMN | Alter_info::ALTER_CHANGE_COLUMN));
10584 75389 bool convert_character_set =
10585
2/2
✓ Branch 0 taken 27743 times.
✓ Branch 1 taken 47646 times.
103132 (alter_info->flags & Alter_info::ALTER_OPTIONS) &&
10586
2/2
✓ Branch 0 taken 1950 times.
✓ Branch 1 taken 25793 times.
27743 (create_info->used_fields & HA_CREATE_USED_CHARSET);
10587
10588 75389 bool encryption_enabled = false;
10589
4/6
✓ Branch 0 taken 75389 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 75389 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 60423 times.
✓ Branch 5 taken 14966 times.
75389 if (altered_table_def->options().exists("encrypt_type")) {
10590 60423 dd::String_type str;
10591
3/6
✓ Branch 0 taken 60423 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 60423 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 60423 times.
✗ Branch 5 not taken.
60423 (void)altered_table_def->options().get("encrypt_type", &str);
10592
10593 60423 encryption_enabled =
10594
1/2
✓ Branch 0 taken 60423 times.
✗ Branch 1 not taken.
60423 0 != my_strcasecmp(system_charset_info, "n", str.c_str());
10595 60423 }
10596
10597 75389 bool single_part_unique_index = false;
10598 /*
10599 Check if we are adding a single-part unique index for a column. If we are,
10600 remove any existing histogram for that column.
10601 */
10602
2/2
✓ Branch 0 taken 12245 times.
✓ Branch 1 taken 63144 times.
75389 if (alter_info->flags & Alter_info::ALTER_ADD_INDEX) {
10603
6/10
✓ Branch 0 taken 12245 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12245 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12245 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 28075 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 28075 times.
✓ Branch 9 taken 12245 times.
40320 for (const auto key : altered_table_def->indexes()) {
10604 /*
10605 A key may have multiple elements, such as (DB_ROW_ID, column). So, check
10606 if we only have a single visible element in the unique/primary key.
10607 */
10608 94535 auto not_hidden = [](const dd::Index_element *element) {
10609 94535 return !element->is_hidden();
10610 };
10611
1/2
✓ Branch 0 taken 28075 times.
✗ Branch 1 not taken.
28075 if ((key->type() == dd::Index::IT_PRIMARY ||
10612
7/8
✓ Branch 0 taken 23734 times.
✓ Branch 1 taken 4341 times.
✓ Branch 2 taken 23734 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10918 times.
✓ Branch 5 taken 12816 times.
✓ Branch 6 taken 9110 times.
✓ Branch 7 taken 18965 times.
43334 key->type() == dd::Index::IT_UNIQUE) &&
10613
7/12
✓ Branch 0 taken 15259 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15259 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15259 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15259 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 15259 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9110 times.
✓ Branch 11 taken 6149 times.
15259 std::count_if(key->elements().begin(), key->elements().end(),
10614 not_hidden) == 1) {
10615 9110 single_part_unique_index = true;
10616
1/2
✓ Branch 0 taken 9110 times.
✗ Branch 1 not taken.
9110 const dd::Index_element *element = *std::find_if(
10617
5/10
✓ Branch 0 taken 9110 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9110 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9110 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9110 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 9110 times.
✗ Branch 9 not taken.
18220 key->elements().begin(), key->elements().end(), not_hidden);
10618
3/6
✓ Branch 0 taken 9110 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9110 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9110 times.
✗ Branch 5 not taken.
9110 columns.emplace(element->column().name().c_str());
10619 }
10620 }
10621 }
10622
10623 /*
10624 If we are changing the character set, find all character columns. TEXT and
10625 similar types will be converted similarly as a BLOB/LONG_BLOB etc. but with
10626 a non-binary character set.
10627 */
10628
2/2
✓ Branch 0 taken 1950 times.
✓ Branch 1 taken 73439 times.
75389 if (convert_character_set) {
10629
6/10
✓ Branch 0 taken 1950 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1950 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1950 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 21453 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 21453 times.
✓ Branch 9 taken 1950 times.
23403 for (const auto column : altered_table_def->columns()) {
10630
3/4
✓ Branch 0 taken 21453 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5897 times.
✓ Branch 3 taken 15556 times.
21453 switch (column->type()) {
10631 5897 case dd::enum_column_types::STRING:
10632 case dd::enum_column_types::VAR_STRING:
10633 case dd::enum_column_types::VARCHAR:
10634 case dd::enum_column_types::TINY_BLOB:
10635 case dd::enum_column_types::MEDIUM_BLOB:
10636 case dd::enum_column_types::LONG_BLOB:
10637 case dd::enum_column_types::BLOB:
10638
3/4
✓ Branch 0 taken 5897 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5421 times.
✓ Branch 3 taken 476 times.
5897 if (column->collation_id() != my_charset_bin.number)
10639
2/4
✓ Branch 0 taken 5421 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5421 times.
✗ Branch 3 not taken.
5421 columns.emplace(column->name().c_str());
10640 5897 break;
10641 15556 default:
10642 15556 continue;
10643 }
10644 }
10645 }
10646
10647
8/8
✓ Branch 0 taken 55727 times.
✓ Branch 1 taken 19662 times.
✓ Branch 2 taken 54725 times.
✓ Branch 3 taken 1002 times.
✓ Branch 4 taken 53644 times.
✓ Branch 5 taken 1081 times.
✓ Branch 6 taken 6833 times.
✓ Branch 7 taken 46811 times.
75389 if (alter_drop_column || convert_character_set || encryption_enabled ||
10648 single_part_unique_index) {
10649 28578 histograms::results_map results;
10650 bool res;
10651
2/2
✓ Branch 0 taken 1400 times.
✓ Branch 1 taken 27178 times.
28578 if (encryption_enabled)
10652
1/2
✓ Branch 0 taken 1400 times.
✗ Branch 1 not taken.
1400 res = histograms::drop_all_histograms(thd, *table, *original_table_def,
10653 results);
10654 else
10655
1/2
✓ Branch 0 taken 27178 times.
✗ Branch 1 not taken.
27178 res = histograms::drop_histograms(thd, *table, columns, false, results);
10656
10657
4/6
✓ Branch 0 taken 28578 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 28577 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
28578 DBUG_EXECUTE_IF("fail_after_drop_histograms", {
10658 my_error(ER_UNABLE_TO_DROP_COLUMN_STATISTICS, MYF(0), "dummy_column",
10659 table->db, table->table_name);
10660 res = true;
10661 });
10662 28578 return res;
10663 28578 }
10664
10665 46811 return false;
10666 }
10667
10668 /**
10669 Rename a table.
10670
10671 @param thd Thread handle
10672 @param base The handlerton handle.
10673 @param old_db The old database name.
10674 @param old_name The old table name.
10675 @param old_fk_db The old table db to be used for
10676 identifying self-referencing FKs
10677 which need to be updated.
10678 @param old_fk_name The old table name to be used for
10679 identifying generated FK names and
10680 self-referencing FKs which need to
10681 be updated.
10682 @param new_schema DD object for the new schema.
10683 @param new_db The new database name.
10684 @param new_name The new table name.
10685 @param flags flags
10686 FN_FROM_IS_TMP old_name is temporary.
10687 FN_TO_IS_TMP new_name is temporary.
10688 NO_FK_CHECKS Don't check FK constraints during rename.
10689 NO_DD_COMMIT Don't commit transaction after updating
10690 data-dictionary.
10691 NO_FK_RENAME Don't change generated foreign key names
10692 during rename.
10693 NO_CC_RENAME Don't change generated check constraint
10694 names during rename.
10695
10696 @note Use of NO_DD_COMMIT flag only allowed for SEs supporting atomic DDL.
10697
10698 @note In case when NO_DD_COMMIT flag was used, the caller must rollback
10699 both statement and transaction on failure. This is necessary to
10700 revert results of handler::ha_rename_table() call in case when
10701 update to the data-dictionary which follows it fails. Also this must
10702 be done before any further accesses to DD.
10703
10704 @return false OK
10705 @return true Error
10706 */
10707
10708 39081 bool mysql_rename_table(THD *thd, handlerton *base, const char *old_db,
10709 const char *old_name, const char *old_fk_db,
10710 const char *old_fk_name, const dd::Schema &new_schema,
10711 const char *new_db, const char *new_name, uint flags) {
10712
1/2
✓ Branch 0 taken 39081 times.
✗ Branch 1 not taken.
39081 DBUG_TRACE;
10713
5/8
✓ Branch 0 taken 39081 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39081 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 39063 times.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
39081 DBUG_PRINT("enter", ("old: '%s'.'%s' new: '%s'.'%s'", old_db, old_name,
10714 new_db, new_name));
10715
10716 /*
10717 Only SEs which support atomic DDL are allowed not to commit
10718 changes to the data-dictionary.
10719 */
10720
3/4
✓ Branch 0 taken 15120 times.
✓ Branch 1 taken 23961 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15120 times.
39081 assert(!(flags & NO_DD_COMMIT) || (base->flags & HTON_SUPPORTS_ATOMIC_DDL));
10721 /*
10722 Check if the new_db database exists. The problem is that some
10723 SE's may not verify if new_db database exists and they might
10724 succeed renaming the table. Moreover, even the InnoDB engine
10725 succeeds renaming the table without verifying if the new_db
10726 database exists when innodb_file_per_table=0.
10727 */
10728
10729 // Check if we hit FN_REFLEN bytes along with file extension.
10730 char from[FN_REFLEN + 1];
10731 char to[FN_REFLEN + 1];
10732 size_t length;
10733 bool was_truncated;
10734
1/2
✓ Branch 0 taken 39081 times.
✗ Branch 1 not taken.
39081 build_table_filename(from, sizeof(from) - 1, old_db, old_name, "",
10735 flags & FN_FROM_IS_TMP);
10736
1/2
✓ Branch 0 taken 39081 times.
✗ Branch 1 not taken.
39081 length = build_table_filename(to, sizeof(to) - 1, new_db, new_name, "",
10737 flags & FN_TO_IS_TMP, &was_truncated);
10738
2/4
✓ Branch 0 taken 39081 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 39081 times.
39081 if (was_truncated || length + reg_ext_length > FN_REFLEN) {
10739 my_error(ER_IDENT_CAUSES_TOO_LONG_PATH, MYF(0), sizeof(to) - 1, to);
10740 return true;
10741 }
10742
10743
1/2
✓ Branch 0 taken 39081 times.
✗ Branch 1 not taken.
39081 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
10744 39081 const dd::Table *from_table_def = nullptr;
10745 39081 dd::Table *to_table_def = nullptr;
10746
10747
6/16
✓ Branch 0 taken 39081 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39081 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39081 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 39081 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 39081 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 39081 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
117243 if (thd->dd_client()->acquire(old_db, old_name, &from_table_def) ||
10748
7/18
✓ Branch 0 taken 39081 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39081 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39081 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 39081 times.
✓ Branch 8 taken 39081 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 39081 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 39081 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
78162 thd->dd_client()->acquire_for_modification(old_db, old_name,
10749 &to_table_def))
10750 return true;
10751
10752 // Tables with a defined secondary engine cannot be renamed, except if the
10753 // renaming is only temporary, which may happen if e.g. ALGORITHM=COPY is
10754 // used.
10755
8/14
✓ Branch 0 taken 39081 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39081 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39081 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 39078 times.
✓ Branch 8 taken 39081 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 39080 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
39084 if (from_table_def->options().exists("secondary_engine") &&
10756
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 !(flags & FN_IS_TMP)) {
10757
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_SECONDARY_ENGINE_DDL, MYF(0));
10758 1 return true;
10759 }
10760
10761 // Set schema id, table name and hidden attribute.
10762
2/4
✓ Branch 0 taken 39080 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39080 times.
✗ Branch 3 not taken.
39080 to_table_def->set_schema_id(new_schema.id());
10763
2/4
✓ Branch 0 taken 39080 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39080 times.
✗ Branch 3 not taken.
39080 to_table_def->set_name(new_name);
10764
3/4
✓ Branch 0 taken 18373 times.
✓ Branch 1 taken 20707 times.
✓ Branch 2 taken 39080 times.
✗ Branch 3 not taken.
39080 to_table_def->set_hidden((flags & FN_TO_IS_TMP)
10765 ? dd::Abstract_table::HT_HIDDEN_DDL
10766 : dd::Abstract_table::HT_VISIBLE);
10767
10768 /* Adjust parent table for self-referencing foreign keys. */
10769
6/10
✓ Branch 0 taken 39080 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39080 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39080 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 241 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 241 times.
✓ Branch 9 taken 39080 times.
39321 for (dd::Foreign_key *fk : *(to_table_def->foreign_keys())) {
10770
2/4
✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241 times.
✗ Branch 3 not taken.
241 if (my_strcasecmp(table_alias_charset,
10771 fk->referenced_table_schema_name().c_str(),
10772
4/4
✓ Branch 0 taken 227 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 236 times.
468 old_fk_db) == 0 &&
10773
4/6
✓ Branch 0 taken 227 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 227 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 222 times.
227 my_strcasecmp(table_alias_charset, fk->referenced_table_name().c_str(),
10774 old_fk_name) == 0) {
10775
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 fk->set_referenced_table_schema_name(new_db);
10776
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 fk->set_referenced_table_name(new_name);
10777 }
10778 }
10779
10780 /*
10781 Unless suppressed update generated foreign key names
10782 (as they have table_name<SE-specific or default suffix>#### format).
10783 */
10784
4/4
✓ Branch 0 taken 2464 times.
✓ Branch 1 taken 36616 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 39079 times.
41544 if (!(flags & NO_FK_RENAME) &&
10785
3/4
✓ Branch 0 taken 2464 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2463 times.
2464 dd::rename_foreign_keys(thd, old_db, old_fk_name, base, new_db,
10786 to_table_def))
10787 1 return true;
10788
10789
4/4
✓ Branch 0 taken 2463 times.
✓ Branch 1 taken 36616 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 39078 times.
41542 if (!(flags & NO_CC_RENAME) &&
10790
3/4
✓ Branch 0 taken 2463 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2462 times.
2463 dd::rename_check_constraints(old_name, to_table_def))
10791 1 return true;
10792
10793 // Get the handler for the table, and issue an error if we cannot load it.
10794 handler *file =
10795
1/2
✓ Branch 0 taken 39078 times.
✗ Branch 1 not taken.
39078 (base == nullptr ? nullptr
10796 39078 : get_new_handler((TABLE_SHARE *)nullptr,
10797
2/4
✓ Branch 0 taken 39078 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39078 times.
✗ Branch 3 not taken.
39078 from_table_def->partition_type() !=
10798 dd::Table::PT_NONE,
10799 39078 thd->mem_root, base));
10800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39078 times.
39078 if (!file) {
10801 my_error(ER_STORAGE_ENGINE_NOT_LOADED, MYF(0), old_db, old_name);
10802 return true;
10803 }
10804
10805 /*
10806 If lower_case_table_names == 2 (case-preserving but case-insensitive
10807 file system) and the storage is not HA_FILE_BASED, we need to provide
10808 a lowercase file name.
10809 */
10810 char lc_from[FN_REFLEN + 1];
10811 char lc_to[FN_REFLEN + 1];
10812 39078 char *from_base = from;
10813 39078 char *to_base = to;
10814
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 39078 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 39078 times.
39078 if (lower_case_table_names == 2 &&
10815 !(file->ha_table_flags() & HA_FILE_BASED)) {
10816 char tmp_name[NAME_LEN + 1];
10817 my_stpcpy(tmp_name, old_name);
10818 my_casedn_str(files_charset_info, tmp_name);
10819 build_table_filename(lc_from, sizeof(lc_from) - 1, old_db, tmp_name, "",
10820 flags & FN_FROM_IS_TMP);
10821 from_base = lc_from;
10822
10823 my_stpcpy(tmp_name, new_name);
10824 my_casedn_str(files_charset_info, tmp_name);
10825 build_table_filename(lc_to, sizeof(lc_to) - 1, new_db, tmp_name, "",
10826 flags & FN_TO_IS_TMP);
10827 to_base = lc_to;
10828 }
10829
10830 /*
10831 Temporarily disable foreign key checks, if requested, while the
10832 handler is involved.
10833 */
10834 39078 ulonglong save_bits = thd->variables.option_bits;
10835
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 39076 times.
39078 if (flags & NO_FK_CHECKS)
10836 2 thd->variables.option_bits |= OPTION_NO_FOREIGN_KEY_CHECKS;
10837
10838 39078 Rename_table_error_handler error_handler;
10839
1/2
✓ Branch 0 taken 39078 times.
✗ Branch 1 not taken.
39078 thd->push_internal_handler(&error_handler);
10840 int error =
10841
1/2
✓ Branch 0 taken 39010 times.
✗ Branch 1 not taken.
39078 file->ha_rename_table(from_base, to_base, from_table_def, to_table_def);
10842
1/2
✓ Branch 0 taken 39010 times.
✗ Branch 1 not taken.
39010 thd->pop_internal_handler();
10843
10844 39010 thd->variables.option_bits = save_bits;
10845
10846
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 38984 times.
39010 if (error != 0) {
10847
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 23 times.
26 if (error == HA_ERR_WRONG_COMMAND)
10848
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
10849 else {
10850 char errbuf[MYSYS_STRERROR_SIZE];
10851
2/4
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
23 my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error,
10852 my_strerror(errbuf, sizeof(errbuf), error));
10853 }
10854 26 destroy(file);
10855 26 return true;
10856 }
10857
10858 /*
10859 Note that before WL#7743 we have renamed table in the data-dictionary
10860 before renaming it in storage engine. However with WL#7743 engines
10861 supporting atomic DDL are allowed to update dd::Table object describing
10862 new version of table in handler::rename_table(). Hence it should saved
10863 after this call.
10864 So to avoid extra calls to DD layer and to keep code simple the
10865 renaming of table in the DD was moved past rename in SE for all SEs.
10866 From crash-safety point of view order doesn't matter for engines
10867 supporting atomic DDL. And for engines which can't do atomic DDL in
10868 either case there are scenarios in which DD and SE get out of sync.
10869 */
10870
1/2
✓ Branch 0 taken 38984 times.
✗ Branch 1 not taken.
38984 bool result = thd->dd_client()->update(to_table_def);
10871
10872 /*
10873 Only rename histograms when this isn't a rename for temporary names
10874 (we will never have a histogram for a temporary name).
10875
10876 Note that this won't catch "ALTER TABLE ... ALGORITHM=COPY" since the COPY
10877 algorithm will first rename to a temporary name, and then to the final name.
10878 That case is handled in the function mysql_alter_table.
10879 */
10880
6/6
✓ Branch 0 taken 38981 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 20628 times.
✓ Branch 3 taken 18353 times.
✓ Branch 4 taken 2292 times.
✓ Branch 5 taken 18336 times.
38984 if (!result && !((flags & FN_TO_IS_TMP) || (flags & FN_FROM_IS_TMP))) {
10881
1/2
✓ Branch 0 taken 2292 times.
✗ Branch 1 not taken.
2292 result = rename_histograms(thd, old_db, old_name, new_db, new_name);
10882 }
10883
10884
2/2
✓ Branch 0 taken 23955 times.
✓ Branch 1 taken 15029 times.
38984 if (!(flags & NO_DD_COMMIT))
10885
1/2
✓ Branch 0 taken 23955 times.
✗ Branch 1 not taken.
23955 result = trans_intermediate_ddl_commit(thd, result);
10886
10887
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 38980 times.
38984 if (result) {
10888 /*
10889 In cases when we are executing atomic DDL it is responsibility of the
10890 caller to revert the changes to SE by rolling back transaction.
10891
10892 If storage engine supports atomic DDL but commit was requested by the
10893 caller the above call to trans_intermediate_ddl_commit() will roll
10894 back the transaction on failure and thus revert change to SE.
10895 */
10896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!(flags & NO_DD_COMMIT))
10897 (void)file->ha_rename_table(to_base, from_base, to_table_def,
10898 const_cast<dd::Table *>(from_table_def));
10899 4 destroy(file);
10900 4 return true;
10901 }
10902 38980 destroy(file);
10903
10904 #ifdef HAVE_PSI_TABLE_INTERFACE
10905 /*
10906 Remove the old table share from the pfs table share array. The new table
10907 share will be created when the renamed table is first accessed.
10908 */
10909 38980 bool temp_table = (bool)is_prefix(old_name, tmp_file_prefix);
10910 PSI_TABLE_CALL(drop_table_share)
10911 38980 (temp_table, old_db, static_cast<int>(strlen(old_db)), old_name,
10912
1/2
✓ Branch 0 taken 38980 times.
✗ Branch 1 not taken.
38980 static_cast<int>(strlen(old_name)));
10913 #endif
10914
10915 38980 return false;
10916 39013 }
10917
10918 /*
10919 Create a table identical to the specified table
10920
10921 SYNOPSIS
10922 mysql_create_like_table()
10923 thd Thread object
10924 table Table list element for target table
10925 src_table Table list element for source table
10926 create_info Create info
10927
10928 RETURN VALUES
10929 false OK
10930 true error
10931 */
10932
10933 1189 bool mysql_create_like_table(THD *thd, TABLE_LIST *table, TABLE_LIST *src_table,
10934 HA_CREATE_INFO *create_info) {
10935
1/2
✓ Branch 0 taken 1189 times.
✗ Branch 1 not taken.
1189 Alter_info local_alter_info(thd->mem_root);
10936
1/2
✓ Branch 0 taken 1189 times.
✗ Branch 1 not taken.
1189 Alter_table_ctx local_alter_ctx; // Not used
10937 1189 bool is_trans = false;
10938 uint not_used;
10939
1/2
✓ Branch 0 taken 1189 times.
✗ Branch 1 not taken.
1189 Tablespace_hash_set tablespace_set(PSI_INSTRUMENT_ME);
10940 1189 handlerton *post_ddl_ht = nullptr;
10941
1/2
✓ Branch 0 taken 1189 times.
✗ Branch 1 not taken.
1189 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
10942
10943
1/2
✓ Branch 0 taken 1189 times.
✗ Branch 1 not taken.
1189 DBUG_TRACE;
10944
10945 /*
10946 We the open source table to get its description in HA_CREATE_INFO
10947 and Alter_info objects. This also acquires a shared metadata lock
10948 on this table which ensures that no concurrent DDL operation will
10949 mess with it.
10950 Also in case when we create non-temporary table open_tables()
10951 call obtains an exclusive metadata lock on target table ensuring
10952 that we can safely perform table creation.
10953 Thus by holding both these locks we ensure that our statement is
10954 properly isolated from all concurrent operations which matter.
10955
10956 CREATE LIKE needs to have the logging format determined if in
10957 MIXED mode and creating LIKE a TEMP table.
10958 */
10959
5/6
✓ Branch 0 taken 1189 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1171 times.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 1171 times.
2360 if (open_tables(thd, &thd->lex->query_tables, &not_used, 0) ||
10960
2/4
✓ Branch 0 taken 1171 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1171 times.
1171 thd->decide_logging_format(thd->lex->query_tables))
10961 18 return true;
10962
1/2
✓ Branch 0 taken 1171 times.
✗ Branch 1 not taken.
1171 src_table->table->use_all_columns();
10963
10964 1171 const dd::Table *src_table_obj = nullptr;
10965
2/2
✓ Branch 0 taken 1106 times.
✓ Branch 1 taken 65 times.
1171 if (!src_table->table->s->tmp_table) {
10966
4/8
✓ Branch 0 taken 1106 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1106 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1106 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1106 times.
1106 if (thd->dd_client()->acquire(src_table->db, src_table->table_name,
10967 &src_table_obj)) {
10968 return true;
10969 }
10970 // Should not happen, we know the table exists and can be opened.
10971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1106 times.
1106 assert(src_table_obj != nullptr);
10972 }
10973
10974
2/4
✓ Branch 0 taken 1171 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1171 times.
✗ Branch 3 not taken.
1171 DEBUG_SYNC(thd, "create_table_like_after_open");
10975
10976 /* Fill HA_CREATE_INFO and Alter_info with description of source table. */
10977
1/2
✓ Branch 0 taken 1171 times.
✗ Branch 1 not taken.
1171 HA_CREATE_INFO local_create_info;
10978
1/2
✓ Branch 0 taken 1171 times.
✗ Branch 1 not taken.
1171 local_create_info.db_type = get_viable_handlerton_for_create_like(
10979
1/2
✓ Branch 0 taken 1171 times.
✗ Branch 1 not taken.
1171 thd, table->table_name, *create_info, src_table->table->s->db_type());
10980
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1168 times.
1171 if (local_create_info.db_type == nullptr) return true;
10981
10982 // This should be ok even if engine substitution has taken place since
10983 // row_type denontes the desired row_type, and a different row_type may be
10984 // assigned to real_row_type later.
10985 1168 local_create_info.row_type = src_table->table->s->row_type;
10986
2/4
✓ Branch 0 taken 1168 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1168 times.
1168 if (mysql_prepare_alter_table(thd, src_table_obj, src_table->table,
10987 &local_create_info, &local_alter_info,
10988 &local_alter_ctx))
10989 return true;
10990
10991
2/4
✓ Branch 0 taken 1168 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1168 times.
1168 if (prepare_check_constraints_for_create_like_table(thd, src_table, table,
10992 &local_alter_info))
10993 return true;
10994
10995
5/8
✓ Branch 0 taken 1168 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1168 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4955 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3787 times.
✓ Branch 7 taken 1168 times.
4955 for (const Create_field &sql_field : local_alter_info.create_list) {
10996
1/2
✓ Branch 0 taken 3787 times.
✗ Branch 1 not taken.
3787 warn_on_deprecated_float_precision(thd, sql_field);
10997
1/2
✓ Branch 0 taken 3787 times.
✗ Branch 1 not taken.
3787 warn_on_deprecated_float_unsigned(thd, sql_field);
10998
1/2
✓ Branch 0 taken 3787 times.
✗ Branch 1 not taken.
3787 warn_on_deprecated_zerofill(thd, sql_field);
10999 }
11000
11001 /*
11002 During open_tables(), the target tablespace name(s) for a table being
11003 created or altered should be locked. However, for 'CREATE TABLE ... LIKE',
11004 the source table is not being created, yet its tablespace name should be
11005 locked since it is used as the target tablespace name for the table being
11006 created. The target tablespace name cannot be set before open_tables()
11007 (which is how we handle this for e.g. CREATE TABLE ... TABLESPACE ...'),
11008 since before open_tables(), the source table itself is not locked, which
11009 means that a DDL operation may sneak in and change the tablespace of the
11010 source table *after* we retrieved it from the .FRM file of the source
11011 table, and *before* the source table itself is locked. Thus, we lock the
11012 target tablespace here in a separate mdl lock acquisition phase after
11013 open_tables(). Since the table is already opened (and locked), we retrieve
11014 the tablespace name from the table share instead of reading it from the
11015 .FRM file.
11016 */
11017
11018 /* Partition info is not handled by mysql_prepare_alter_table() call. */
11019
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 1066 times.
1168 if (src_table->table->part_info)
11020
1/2
✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
102 thd->work_part_info = src_table->table->part_info->get_clone(thd);
11021
11022 // Add the tablespace name, if used.
11023
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1123 times.
1168 if (src_table->table->s->tablespace &&
11024
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 strlen(src_table->table->s->tablespace) > 0) {
11025
4/6
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 42 times.
45 assert(
11026 src_table->table->s->tmp_table ||
11027 thd->mdl_context.owns_equal_or_stronger_lock(
11028 MDL_key::TABLE, src_table->db, src_table->table_name, MDL_SHARED));
11029
11030
2/4
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
45 tablespace_set.insert(src_table->table->s->tablespace);
11031 }
11032
11033 // Add tablespace names used under partition/subpartition definitions.
11034
2/4
✓ Branch 0 taken 1168 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1168 times.
1168 if (fill_partition_tablespace_names(src_table->table->part_info,
11035 &tablespace_set))
11036 return true;
11037
11038 /*
11039 After we have identified the tablespace names, we iterate
11040 over the names and acquire MDL lock for each of them.
11041 */
11042
2/4
✓ Branch 0 taken 1168 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1168 times.
1168 if (lock_tablespace_names(thd, &tablespace_set,
11043 thd->variables.lock_wait_timeout, thd->mem_root)) {
11044 return true;
11045 }
11046
11047 /*
11048 Adjust description of source table before using it for creation of
11049 target table.
11050
11051 Similarly to SHOW CREATE TABLE we ignore MAX_ROWS attribute of
11052 temporary table which represents I_S table.
11053 */
11054
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1162 times.
1168 if (src_table->schema_table) local_create_info.max_rows = 0;
11055 /* Set IF NOT EXISTS option as in the CREATE TABLE LIKE statement. */
11056 1168 local_create_info.options |=
11057 1168 create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
11058 /* Replace type of source table with one specified in the statement. */
11059 1168 local_create_info.options &= ~HA_LEX_CREATE_TMP_TABLE;
11060 1168 local_create_info.options |= create_info->options & HA_LEX_CREATE_TMP_TABLE;
11061 /* Reset auto-increment counter for the new table. */
11062 1168 local_create_info.auto_increment_value = 0;
11063 /*
11064 Do not inherit values of DATA and INDEX DIRECTORY options from
11065 the original table. This is documented behavior.
11066 */
11067 1168 local_create_info.data_file_name = local_create_info.index_file_name =
11068 nullptr;
11069 1168 local_create_info.alias = create_info->alias;
11070
11071 /*
11072 Keep tablespace, only if it was specified explicitly in CREATE
11073 TABLE when source table was created.
11074 */
11075
7/8
✓ Branch 0 taken 1103 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 1103 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1066 times.
✓ Branch 5 taken 37 times.
✓ Branch 6 taken 1066 times.
✓ Branch 7 taken 102 times.
1168 if (src_table_obj && !src_table_obj->is_explicit_tablespace()) {
11076 1066 local_create_info.tablespace = nullptr;
11077 }
11078
11079 /*
11080 Lock the FK children, in case the new table introduces a missing parent.
11081 */
11082
1/2
✓ Branch 0 taken 1152 times.
✗ Branch 1 not taken.
1152 if (!(table->table || table->is_view()) &&
11083
6/6
✓ Branch 0 taken 1152 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 1079 times.
✓ Branch 3 taken 73 times.
✓ Branch 4 taken 834 times.
✓ Branch 5 taken 334 times.
3399 !(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
11084
2/2
✓ Branch 0 taken 834 times.
✓ Branch 1 taken 245 times.
1079 (local_create_info.db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS)) {
11085 /*
11086 CREATE TABLE LIKE fails under LOCK TABLES at open_tables() time if
11087 target table doesn't exist already. So we don't need to handle
11088 LOCK TABLES case here by checking that parent tables for new FKs
11089 are properly locked and there are no orphan child tables for which
11090 table being created will become parent.
11091 */
11092
2/4
✓ Branch 0 taken 834 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 834 times.
✗ Branch 3 not taken.
834 assert(thd->locked_tables_mode != LTM_LOCK_TABLES &&
11093 thd->locked_tables_mode != LTM_PRELOCKED_UNDER_LOCK_TABLES);
11094
11095
1/2
✓ Branch 0 taken 834 times.
✗ Branch 1 not taken.
834 MDL_request_list mdl_requests;
11096
11097
3/10
✓ Branch 0 taken 834 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 834 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 834 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1668 if ((!dd::get_dictionary()->is_dd_table_name(table->db,
11098 834 table->table_name) &&
11099
2/4
✓ Branch 0 taken 834 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 834 times.
✗ Branch 3 not taken.
834 collect_fk_children(thd, table->db, table->table_name,
11100 local_create_info.db_type, MDL_EXCLUSIVE,
11101
5/10
✓ Branch 0 taken 834 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 834 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 834 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 834 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 834 times.
✗ Branch 9 not taken.
2502 &mdl_requests)) ||
11102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 834 times.
834 (!mdl_requests.is_empty() &&
11103 thd->mdl_context.acquire_locks(&mdl_requests,
11104 thd->variables.lock_wait_timeout)))
11105 return true;
11106 }
11107
11108
3/4
✓ Branch 0 taken 1168 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 1141 times.
1168 if (mysql_create_table_no_lock(
11109 thd, table->db, table->table_name, &local_create_info,
11110 &local_alter_info, 0,
11111 false, // No FKs, no need to lookup parent keys
11112 &is_trans, &post_ddl_ht))
11113 27 goto err;
11114
11115 /*
11116 Ensure that table or view does not exist and we have an exclusive lock on
11117 target table if we are creating non-temporary table. In LOCK TABLES mode
11118 the only way the table is locked, is if it already exists (since you cannot
11119 LOCK TABLE a non-existing table). And the only way we then can end up here
11120 is if IF EXISTS was used.
11121 */
11122
8/20
✓ Branch 0 taken 1130 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 1130 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1059 times.
✓ Branch 5 taken 71 times.
✓ Branch 6 taken 1059 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1059 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1059 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
1141 assert(
11123 table->table || table->is_view() ||
11124 (create_info->options & HA_LEX_CREATE_TMP_TABLE) ||
11125 (thd->locked_tables_mode != LTM_LOCK_TABLES &&
11126 thd->mdl_context.owns_equal_or_stronger_lock(
11127 MDL_key::TABLE, table->db, table->table_name, MDL_EXCLUSIVE)) ||
11128 (thd->locked_tables_mode == LTM_LOCK_TABLES &&
11129 (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) &&
11130 thd->mdl_context.owns_equal_or_stronger_lock(
11131 MDL_key::TABLE, table->db, table->table_name, MDL_SHARED_NO_WRITE)));
11132
11133
2/4
✓ Branch 0 taken 1141 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1141 times.
✗ Branch 3 not taken.
1141 DEBUG_SYNC(thd, "create_table_like_before_binlog");
11134
11135 /*
11136 CREATE TEMPORARY TABLE doesn't terminate a transaction. Calling
11137 stmt.mark_created_temp_table() guarantees the transaction can be binlogged
11138 correctly.
11139 */
11140
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 1068 times.
1141 if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
11141
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 thd->get_transaction()->mark_created_temp_table(Transaction_ctx::STMT);
11142
11143 /*
11144 We have to write the query before we unlock the tables.
11145 */
11146
7/8
✓ Branch 0 taken 1141 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1102 times.
✓ Branch 3 taken 39 times.
✓ Branch 4 taken 932 times.
✓ Branch 5 taken 170 times.
✓ Branch 6 taken 932 times.
✓ Branch 7 taken 209 times.
2243 if (!thd->is_current_stmt_binlog_disabled() &&
11147 1102 thd->is_current_stmt_binlog_format_row()) {
11148 /*
11149 Since temporary tables are not replicated under row-based
11150 replication, CREATE TABLE ... LIKE ... needs special
11151 treatment. We have four cases to consider, according to the
11152 following decision table:
11153
11154 ==== ========= ========= ==============================
11155 Case Target Source Write to binary log
11156 ==== ========= ========= ==============================
11157 1 normal normal Original statement
11158 2 normal temporary Generated statement
11159 3 temporary normal Nothing
11160 4 temporary temporary Nothing
11161 ==== ========= ========= ==============================
11162 */
11163
2/2
✓ Branch 0 taken 885 times.
✓ Branch 1 taken 47 times.
932 if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
11164
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 859 times.
885 if (src_table->table->s->tmp_table) // Case 2
11165 {
11166 char buf[2048];
11167 26 String query(buf, sizeof(buf), system_charset_info);
11168 26 query.length(0); // Have to zero it since constructor doesn't
11169
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN);
11170 26 bool new_table = false; // Whether newly created table is open.
11171
11172 /*
11173 The condition avoids a crash as described in BUG#48506. Other
11174 binlogging problems related to CREATE TABLE IF NOT EXISTS LIKE
11175 when the existing object is a view will be solved by BUG 47442.
11176 */
11177
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (!table->is_view()) {
11178
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 if (!table->table) {
11179 /*
11180 In order for store_create_info() to work we need to open
11181 destination table if it is not already open (i.e. if it
11182 has not existed before). We don't need acquire metadata
11183 lock in order to do this as we already hold exclusive
11184 lock on this table. The table will be closed by
11185 close_thread_table() at the end of this branch.
11186 */
11187
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 bool result = open_table(thd, table, &ot_ctx);
11188
11189 /*
11190 Play safe, ensure that we won't poison TDC/TC by storing
11191 not-yet-committed table definition there.
11192 */
11193
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN, table->db,
11194 table->table_name, false);
11195
11196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (result) goto err;
11197 24 new_table = true;
11198 }
11199
11200 /*
11201 After opening a MERGE table add the children to the query list of
11202 tables, so that children tables info can be used on "CREATE TABLE"
11203 statement generation by the binary log.
11204 Note that placeholders don't have the handler open.
11205 */
11206
2/4
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26 times.
26 if (table->table->file->ha_extra(HA_EXTRA_ADD_CHILDREN_LIST)) {
11207 if (new_table) {
11208 assert(thd->open_tables == table->table);
11209 close_thread_table(thd, &thd->open_tables);
11210 table->table = nullptr;
11211 }
11212 goto err;
11213 }
11214
11215 /*
11216 As the reference table is temporary and may not exist on slave, we
11217 must force the ENGINE to be present into CREATE TABLE.
11218 */
11219 26 create_info->used_fields |= HA_CREATE_USED_ENGINE;
11220
11221
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 bool result [[maybe_unused]] = store_create_info(
11222 thd, table, &query, create_info, true /* show_database */,
11223 false /* SHOW CREATE TABLE */);
11224
11225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 assert(result == 0); // store_create_info() always return 0
11226
11227
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
26 if (new_table) {
11228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 assert(thd->open_tables == table->table);
11229 /*
11230 When opening the table, we ignored the locked tables
11231 (MYSQL_OPEN_GET_NEW_TABLE). Now we can close the table
11232 without risking to close some locked table.
11233 */
11234
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 close_thread_table(thd, &thd->open_tables);
11235 24 table->table = nullptr;
11236 }
11237
11238
2/4
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 26 times.
26 if (write_bin_log(thd, true, query.ptr(), query.length(), is_trans))
11239 goto err;
11240 }
11241
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 } else // Case 1
11242
4/8
✓ Branch 0 taken 859 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 859 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 859 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 859 times.
859 if (write_bin_log(thd, true, thd->query().str, thd->query().length,
11243 is_trans))
11244 goto err;
11245 }
11246 /*
11247 Case 3 and 4 does nothing under RBR
11248 */
11249
4/8
✓ Branch 0 taken 209 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 209 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 209 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 209 times.
209 } else if (write_bin_log(thd, true, thd->query().str, thd->query().length,
11250 is_trans))
11251 goto err;
11252
11253
2/2
✓ Branch 0 taken 1068 times.
✓ Branch 1 taken 73 times.
1141 if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
11254 /*
11255 Update the FK information for the children that were locked previously.
11256 */
11257
1/2
✓ Branch 0 taken 1059 times.
✗ Branch 1 not taken.
1059 if (!(table->table || table->is_view()) &&
11258
13/22
✓ Branch 0 taken 1059 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 1059 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1059 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1059 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1059 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1059 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1059 times.
✓ Branch 13 taken 9 times.
✓ Branch 14 taken 1059 times.
✓ Branch 15 taken 9 times.
✓ Branch 16 taken 827 times.
✓ Branch 17 taken 241 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
3186 !dd::get_dictionary()->is_dd_table_name(table->db, table->table_name) &&
11259
2/2
✓ Branch 0 taken 827 times.
✓ Branch 1 taken 232 times.
1059 (local_create_info.db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS)) {
11260 827 const dd::Table *new_table = nullptr;
11261
4/8
✓ Branch 0 taken 827 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 827 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 827 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 827 times.
827 if (thd->dd_client()->acquire(table->db, table->table_name, &new_table))
11262 goto err;
11263 else {
11264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 827 times.
827 assert(new_table != nullptr);
11265 /*
11266 If we are to support FKs for storage engines which don't support
11267 atomic DDL we need to decide what to do for such SEs in case of
11268 failure to update children definitions and adjust code accordingly.
11269 */
11270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 827 times.
827 assert(is_trans);
11271
11272
1/2
✓ Branch 0 taken 827 times.
✗ Branch 1 not taken.
827 if (adjust_fk_children_after_parent_def_change(
11273 thd, table->db, table->table_name, local_create_info.db_type,
11274
2/4
✓ Branch 0 taken 827 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 827 times.
1654 new_table, nullptr) ||
11275
2/4
✓ Branch 0 taken 827 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 827 times.
827 adjust_fk_parents(thd, table->db, table->table_name, true, nullptr))
11276 goto err;
11277 }
11278 }
11279
11280 /*
11281 Update view metadata. Use nested block to ensure that TDC
11282 invalidation happens before commit.
11283 */
11284 {
11285
1/2
✓ Branch 0 taken 1068 times.
✗ Branch 1 not taken.
1068 Uncommitted_tables_guard uncommitted_tables(thd);
11286
11287
5/6
✓ Branch 0 taken 1059 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 1059 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1059 times.
✓ Branch 5 taken 9 times.
1068 if (!table->table && !table->is_view())
11288
1/2
✓ Branch 0 taken 1059 times.
✗ Branch 1 not taken.
1059 uncommitted_tables.add_table(table);
11289
11290
3/4
✓ Branch 0 taken 1068 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1066 times.
1068 if (update_referencing_views_metadata(thd, table, !is_trans,
11291 &uncommitted_tables))
11292 2 goto err;
11293
2/2
✓ Branch 0 taken 1066 times.
✓ Branch 1 taken 2 times.
1068 }
11294
11295
5/10
✓ Branch 0 taken 1066 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1066 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1066 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1066 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1066 times.
1066 if (trans_commit_stmt(thd) || trans_commit_implicit(thd)) goto err;
11296
11297
3/4
✓ Branch 0 taken 825 times.
✓ Branch 1 taken 241 times.
✓ Branch 2 taken 825 times.
✗ Branch 3 not taken.
1066 if (post_ddl_ht) post_ddl_ht->post_ddl(thd);
11298 }
11299 1139 return false;
11300
11301 29 err:
11302
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 3 times.
29 if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
11303
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 trans_rollback_stmt(thd);
11304 /*
11305 Full rollback in case we have THD::transaction_rollback_request
11306 and to synchronize DD state in cache and on disk (as statement
11307 rollback doesn't clear DD cache of modified uncommitted objects).
11308 */
11309
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 trans_rollback(thd);
11310
11311
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
26 if (post_ddl_ht) post_ddl_ht->post_ddl(thd);
11312 }
11313 29 return true;
11314 1189 }
11315
11316 /* table_list should contain just one table */
11317 1200 bool Sql_cmd_discard_import_tablespace::mysql_discard_or_import_tablespace(
11318 THD *thd, TABLE_LIST *table_list) {
11319 1200 Alter_table_prelocking_strategy alter_prelocking_strategy;
11320 int error;
11321
1/2
✓ Branch 0 taken 1200 times.
✗ Branch 1 not taken.
1200 DBUG_TRACE;
11322
11323 /*
11324 Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
11325 ALTER TABLE
11326 */
11327
11328 /*
11329 DISCARD/IMPORT TABLESPACE do not respect ALGORITHM and LOCK clauses.
11330 */
11331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1200 times.
1200 if (m_alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_DEFAULT) {
11332 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0),
11333 "LOCK=NONE/SHARED/EXCLUSIVE", "LOCK=DEFAULT");
11334 return true;
11335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1200 times.
1200 } else if (m_alter_info->requested_algorithm !=
11336 Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT) {
11337 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0),
11338 "ALGORITHM=COPY/INPLACE/INSTANT", "ALGORITHM=DEFAULT");
11339 return true;
11340 }
11341
11342
1/2
✓ Branch 0 taken 1200 times.
✗ Branch 1 not taken.
1200 THD_STAGE_INFO(thd, stage_discard_or_import_tablespace);
11343
11344 /*
11345 Adjust values of table-level and metadata which was set in parser
11346 for the case general ALTER TABLE.
11347 */
11348 1200 table_list->mdl_request.set_type(MDL_EXCLUSIVE);
11349 1200 table_list->set_lock({TL_WRITE, THR_DEFAULT});
11350 /* Do not open views. */
11351 1200 table_list->required_type = dd::enum_table_type::BASE_TABLE;
11352
11353
2/4
✓ Branch 0 taken 1200 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1200 times.
1200 if (open_and_lock_tables(thd, table_list, 0, &alter_prelocking_strategy)) {
11354 /* purecov: begin inspected */
11355 return true;
11356 /* purecov: end */
11357 }
11358
11359
2/2
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 820 times.
1200 if (table_list->table->part_info) {
11360 /*
11361 If not ALL is mentioned and there is at least one specified
11362 [sub]partition name, use the specified [sub]partitions only.
11363 */
11364
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 212 times.
380 if (m_alter_info->partition_names.elements > 0 &&
11365
1/2
✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
168 !(m_alter_info->flags & Alter_info::ALTER_ALL_PARTITION)) {
11366 168 table_list->partition_names = &m_alter_info->partition_names;
11367 /* Set all [named] partitions as used. */
11368
3/4
✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 166 times.
168 if (table_list->table->part_info->set_partition_bitmaps(table_list))
11369 2 return true;
11370 }
11371 } else {
11372
2/2
✓ Branch 0 taken 817 times.
✓ Branch 1 taken 3 times.
820 if (m_alter_info->partition_names.elements > 0 ||
11373
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 816 times.
817 m_alter_info->flags & Alter_info::ALTER_ALL_PARTITION) {
11374 /* Don't allow DISCARD/IMPORT PARTITION on a nonpartitioned table */
11375
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
11376 4 return true;
11377 }
11378 }
11379
11380 1194 bool is_non_tmp_table = (table_list->table->s->tmp_table == NO_TMP_TABLE);
11381
1/2
✓ Branch 0 taken 1194 times.
✗ Branch 1 not taken.
1194 handlerton *hton = table_list->table->s->db_type();
11382
11383
1/2
✓ Branch 0 taken 1194 times.
✗ Branch 1 not taken.
1194 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
11384 1194 dd::Table *table_def = nullptr;
11385
11386
2/2
✓ Branch 0 taken 1185 times.
✓ Branch 1 taken 9 times.
1194 if (is_non_tmp_table) {
11387
4/8
✓ Branch 0 taken 1185 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1185 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1185 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1185 times.
1185 if (thd->dd_client()->acquire_for_modification(
11388 table_list->db, table_list->table_name, &table_def))
11389 return true;
11390
11391 /* Table was successfully opened above. */
11392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1185 times.
1185 assert(table_def != nullptr);
11393 } else
11394 9 table_def = table_list->table->s->tmp_table_def;
11395
11396 /*
11397 Under LOCK TABLES we need to upgrade SNRW metadata lock to X lock
11398 before doing discard or import of tablespace.
11399
11400 Skip this step for temporary tables as metadata locks are not
11401 applicable for them.
11402
11403 Remember the ticket for the future downgrade.
11404 */
11405 1194 MDL_ticket *mdl_ticket = nullptr;
11406
11407
2/2
✓ Branch 0 taken 1185 times.
✓ Branch 1 taken 9 times.
1194 if (is_non_tmp_table &&
11408
2/2
✓ Branch 0 taken 1177 times.
✓ Branch 1 taken 8 times.
1185 (thd->locked_tables_mode == LTM_LOCK_TABLES ||
11409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1177 times.
1177 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) {
11410 8 mdl_ticket = table_list->table->mdl_ticket;
11411
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if (thd->mdl_context.upgrade_shared_lock(mdl_ticket, MDL_EXCLUSIVE,
11412 thd->variables.lock_wait_timeout))
11413 return true;
11414 }
11415
11416 /*
11417 The parser sets a flag in the Alter_info struct to indicate
11418 whether this is DISCARD or IMPORT. The flag is used for two purposes:
11419
11420 1. To submit the appropriate parameter to the SE to indicate which
11421 operation is to be performed (see the source code below).
11422 2. To implement a callback function (the plugin API function
11423 'thd_tablespace_op()') allowing the SEs supporting these
11424 operations to check if we are doing a DISCARD or IMPORT, in order to
11425 suppress errors otherwise being thrown when opening tables with a
11426 missing tablespace.
11427 */
11428
11429
2/4
✓ Branch 0 taken 1194 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1194 times.
1194 if (table_list->table->has_compressed_columns()) {
11430 /*
11431 ALTER TABLE ... DISCARD/IMPORT TABLESPACE is not supported for tables
11432 with compressed columns.
11433 */
11434 error = HA_ERR_WRONG_COMMAND;
11435 } else {
11436 1194 const bool discard =
11437 1194 (m_alter_info->flags & Alter_info::ALTER_DISCARD_TABLESPACE);
11438
1/2
✓ Branch 0 taken 1168 times.
✗ Branch 1 not taken.
1194 error = table_list->table->file->ha_discard_or_import_tablespace(discard,
11439 table_def);
11440 }
11441
11442
1/2
✓ Branch 0 taken 1168 times.
✗ Branch 1 not taken.
1168 THD_STAGE_INFO(thd, stage_end);
11443
11444
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 928 times.
1168 if (error) {
11445
1/2
✓ Branch 0 taken 240 times.
✗ Branch 1 not taken.
240 table_list->table->file->print_error(error, MYF(0));
11446 } else {
11447 // When we have imported a tablespace we need to remove any old SDIs stored
11448 // in it because new SDIs need not have the same keys as those found in the
11449 // tablspace.
11450
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 593 times.
928 if ((m_alter_info->flags & Alter_info::ALTER_IMPORT_TABLESPACE)) {
11451 // When we have imported tablespaces for individual partitions, we must
11452 // limit SDI removal to the tablespaces for the mentioned partitions.
11453
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 267 times.
335 if (m_alter_info->partition_names.elements > 0) {
11454
3/10
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 68 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
68 DBUG_PRINT("ddsdi", ("Import partition tablespace for query:%s",
11455 thd->query().str));
11456 68 const auto &pi = *table_list->table->part_info;
11457 #ifndef NDEBUG
11458
5/8
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 87 times.
✓ Branch 7 taken 68 times.
155 for (const auto &pn : *table_list->partition_names) {
11459
3/8
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 87 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
87 DBUG_PRINT("ddsdi", ("Importing partition %s", pn.ptr()));
11460 }
11461 const auto &part_name_hash =
11462 68 *static_cast<Partition_share *>(table_list->table->s->ha_share)
11463 68 ->partition_name_hash;
11464 #endif /* NDEBUG */
11465 68 uint pa_id = 0;
11466
3/4
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 422 times.
✓ Branch 3 taken 68 times.
490 for (const auto &lp : *table_def->leaf_partitions()) {
11467 #ifndef NDEBUG
11468 // Verify that part_id corresponds to index in leaf partition vector.
11469
1/2
✓ Branch 0 taken 422 times.
✗ Branch 1 not taken.
422 auto part_def = find_or_nullptr(
11470 part_name_hash,
11471
3/6
✓ Branch 0 taken 422 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 422 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 422 times.
✗ Branch 5 not taken.
844 std::string(lp->name().c_str(), lp->name().length()));
11472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 422 times.
422 assert(part_def != nullptr);
11473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 422 times.
422 assert(part_def->part_id == pa_id);
11474 #endif /* NDEBUG */
11475
3/12
✓ Branch 0 taken 422 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 422 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 422 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
422 DBUG_PRINT("ddsdi",
11476 ("Checking leaf partition %s, is_used(pa_id:%u):%s",
11477 lp->name().c_str(), pa_id,
11478 pi.is_partition_used(pa_id) ? "true" : "false"));
11479
3/4
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 329 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 422 times.
515 if (pi.is_partition_used(pa_id) &&
11480
2/4
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 93 times.
93 dd::sdi::drop_all_for_part(thd, lp)) {
11481 error = 1;
11482 break;
11483 }
11484 422 ++pa_id;
11485 }
11486 } else {
11487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 267 times.
267 assert(m_alter_info->partition_names.elements == 0);
11488 // We get here when we have imported a table tablespace, or all
11489 // partition tablespaces. In this case, we remove SDIs from all
11490 // tablespaces associated with the table.
11491
2/4
✓ Branch 0 taken 267 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 267 times.
267 if (dd::sdi::drop_all_for_table(thd, table_def)) {
11492 error = 1;
11493 }
11494 }
11495 }
11496
11497 /*
11498 Storage engine supporting atomic DDL can fully rollback discard/
11499 import if any problem occurs. This will happen during statement
11500 rollback.
11501
11502 In case of success we need to save dd::Table object which might
11503 have been updated by SE. If this step or subsequent write to binary
11504 log fail then statement rollback will also restore status quo ante.
11505 */
11506
1/2
✓ Branch 0 taken 928 times.
✗ Branch 1 not taken.
928 if (!error && is_non_tmp_table &&
11507
3/6
✓ Branch 0 taken 928 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 928 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 928 times.
2784 (hton->flags & HTON_SUPPORTS_ATOMIC_DDL) &&
11508
2/4
✓ Branch 0 taken 928 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 928 times.
928 thd->dd_client()->update(table_def))
11509 error = 1;
11510
11511
1/2
✓ Branch 0 taken 928 times.
✗ Branch 1 not taken.
928 if (!error)
11512
2/4
✓ Branch 0 taken 928 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 928 times.
✗ Branch 3 not taken.
928 error = write_bin_log(thd, false, thd->query().str, thd->query().length,
11513
1/2
✓ Branch 0 taken 928 times.
✗ Branch 1 not taken.
928 (hton->flags & HTON_SUPPORTS_ATOMIC_DDL));
11514
11515 /*
11516 TODO: In theory since we have updated table definition in the
11517 data-dictionary above we need to remove its TABLE/TABLE_SHARE
11518 from TDC now. However this makes InnoDB to produce too many
11519 warnings about discarded tablespace which are not always well
11520 justified. So this code should be enabled after InnoDB is
11521 adjusted to be less verbose in these cases.
11522 */
11523 #ifdef NEEDS_SUPPORT_FROM_INNODB
11524 if (is_non_tmp_table)
11525 close_all_tables_for_name(thd, table_list->table->s, false, nullptr);
11526 table_list->table = nullptr; // Safety.
11527 #endif
11528 }
11529
11530
6/10
✓ Branch 0 taken 928 times.
✓ Branch 1 taken 240 times.
✓ Branch 2 taken 928 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 928 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 928 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 928 times.
1168 if (!error) error = trans_commit_stmt(thd) || trans_commit_implicit(thd);
11531
11532
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 928 times.
1168 if (error) {
11533
1/2
✓ Branch 0 taken 240 times.
✗ Branch 1 not taken.
240 trans_rollback_stmt(thd);
11534
1/2
✓ Branch 0 taken 240 times.
✗ Branch 1 not taken.
240 trans_rollback_implicit(thd);
11535 }
11536
11537
4/4
✓ Branch 0 taken 1159 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 1156 times.
✓ Branch 3 taken 3 times.
1168 if (is_non_tmp_table && (hton->flags & HTON_SUPPORTS_ATOMIC_DDL) &&
11538
1/2
✓ Branch 0 taken 1156 times.
✗ Branch 1 not taken.
1156 hton->post_ddl)
11539
1/2
✓ Branch 0 taken 1156 times.
✗ Branch 1 not taken.
1156 hton->post_ddl(thd);
11540
11541
5/8
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1158 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1168 times.
1168 if (thd->locked_tables_mode && thd->locked_tables_list.reopen_tables(thd))
11542 error = 1;
11543
11544
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1160 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
1168 if (mdl_ticket) mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
11545
11546
2/2
✓ Branch 0 taken 928 times.
✓ Branch 1 taken 240 times.
1168 if (error == 0) {
11547
1/2
✓ Branch 0 taken 928 times.
✗ Branch 1 not taken.
928 my_ok(thd);
11548 928 return false;
11549 }
11550
11551 240 return true;
11552 1174 }
11553
11554 /**
11555 * Loads a table into a secondary engine if SECONDARY_LOAD, unloads from
11556 * secondary engine if SECONDARY_UNLOAD.
11557 *
11558 * @param thd Thread handler.
11559 * @param table_list Table to load.
11560 *
11561 * @return True if error, false otherwise.
11562 */
11563 133 bool Sql_cmd_secondary_load_unload::mysql_secondary_load_or_unload(
11564 THD *thd, TABLE_LIST *table_list) {
11565 133 Alter_table_prelocking_strategy alter_prelocking_strategy;
11566
11567 // Because SECONDARY_LOAD and SECONDARY_UNLOAD are standalone alter table
11568 // actions, it should be impossible to set ALGORITHM and LOCK.
11569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
133 assert(m_alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_DEFAULT);
11570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
133 assert(m_alter_info->requested_algorithm ==
11571 Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT);
11572
11573 // Load if SECONDARY_LOAD, unload if SECONDARY_UNLOAD
11574 133 const bool is_load = m_alter_info->flags & Alter_info::ALTER_SECONDARY_LOAD;
11575
11576 // SECONDARY_LOAD operation requires SNW MDL for its initial phase, which is
11577 // downgraded to SU lock (by RAPID SE) and eventually upgraded to X lock (by
11578 // SQL-layer) before updating Table Definition Cache.
11579 133 const enum_mdl_type mdl_type =
11580
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 37 times.
133 is_load ? SECLOAD_SCAN_START_MDL : MDL_EXCLUSIVE;
11581
11582 133 table_list->mdl_request.set_type(mdl_type);
11583
11584 // Always use isolation level READ_COMMITTED to ensure consistent view of
11585 // table data during entire load operation. Higher isolation levels provide no
11586 // benefits for this operation and could impact performance, so it's fine to
11587 // downgrade from both REPEATABLE_READ and SERIALIZABLE.
11588 133 const enum_tx_isolation orig_tx_isolation = thd->tx_isolation;
11589 auto tx_isolation_guard = create_scope_guard(
11590
1/2
✓ Branch 0 taken 133 times.
✗ Branch 1 not taken.
133 [thd, orig_tx_isolation] { thd->tx_isolation = orig_tx_isolation; });
11591 133 thd->tx_isolation = ISO_READ_COMMITTED;
11592
11593 // Open base table.
11594 133 table_list->required_type = dd::enum_table_type::BASE_TABLE;
11595
3/4
✓ Branch 0 taken 133 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 131 times.
133 if (open_and_lock_tables(thd, table_list, 0, &alter_prelocking_strategy))
11596 2 return true;
11597
11598 // SECONDARY_LOAD/SECONDARY_UNLOAD requires a secondary engine.
11599
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 126 times.
131 if (!table_list->table->s->has_secondary_engine()) {
11600
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_error(ER_SECONDARY_ENGINE, MYF(0), "No secondary engine defined");
11601 5 return true;
11602 }
11603
11604
6/6
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 92 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 32 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 124 times.
126 if (!is_load && secondary_engine_lock_tables_mode(*thd)) {
11605
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (thd->mdl_context.upgrade_shared_lock(table_list->table->mdl_ticket,
11606 mdl_type,
11607 thd->variables.lock_wait_timeout))
11608 return true;
11609 }
11610
2/4
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 126 times.
126 assert(thd->mdl_context.owns_equal_or_stronger_lock(
11611 MDL_key::TABLE, table_list->db, table_list->table_name, mdl_type));
11612
11613 126 MDL_ticket *mdl_ticket = table_list->table->mdl_ticket;
11614 130 auto downgrade_guard = create_scope_guard([mdl_ticket, thd] {
11615 // Under LOCK TABLES, downgrade to MDL_SHARED_NO_READ_WRITE after all
11616 // operations have completed.
11617
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 122 times.
126 if (secondary_engine_lock_tables_mode(*thd)) {
11618 4 mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
11619 }
11620
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 });
11621
11622 // Omit hidden generated columns and columns marked as NOT SECONDARY from
11623 // read_set. It is the responsibility of the secondary engine handler to load
11624 // only the columns included in the read_set.
11625 126 bitmap_clear_all(table_list->table->read_set);
11626
2/2
✓ Branch 0 taken 318 times.
✓ Branch 1 taken 126 times.
444 for (Field **field = table_list->table->field; *field != nullptr; ++field) {
11627 // Skip hidden generated columns.
11628
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 317 times.
318 if (bitmap_is_set(&table_list->table->fields_for_functional_indexes,
11629 318 (*field)->field_index()))
11630 1 continue;
11631
11632 // Skip columns marked as NOT SECONDARY.
11633
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 306 times.
317 if ((*field)->is_flag_set(NOT_SECONDARY_FLAG)) continue;
11634
11635 // Mark column as eligible for loading.
11636
1/2
✓ Branch 0 taken 306 times.
✗ Branch 1 not taken.
306 table_list->table->mark_column_used(*field, MARK_COLUMNS_READ);
11637 }
11638
11639 // It should not have been possible to define a temporary table with a
11640 // secondary engine.
11641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 assert(table_list->table->s->tmp_table == NO_TMP_TABLE);
11642
11643
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 handlerton *hton = table_list->table->s->db_type();
11644
3/6
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 126 times.
✗ Branch 5 not taken.
126 assert(hton->flags & HTON_SUPPORTS_ATOMIC_DDL &&
11645 hton->flags & HTON_SUPPORTS_SECONDARY_ENGINE &&
11646 hton->post_ddl != nullptr);
11647
11648
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
11649 126 dd::Table *table_def = nullptr;
11650
4/8
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 126 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 126 times.
126 if (thd->dd_client()->acquire_for_modification(
11651 table_list->db, table_list->table_name, &table_def))
11652 return true;
11653
11654 // Cleanup that must be done regardless of commit or rollback.
11655 256 auto cleanup = [thd, hton]() {
11656 126 hton->post_ddl(thd);
11657
11658 // reopen_tables() will only affect tables which have been closed by
11659 // close_all_tables_for_name(), which means it will do reopen only while we
11660 // hold X lock on table.
11661
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 122 times.
130 return thd->locked_tables_mode &&
11662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
130 thd->locked_tables_list.reopen_tables(thd);
11663 126 };
11664
11665 // This scope guard is responsible for rolling back the transaction in case of
11666 // any errors.
11667 12 auto rollback_guard = create_scope_guard([thd, cleanup] {
11668 6 trans_rollback_stmt(thd);
11669 6 trans_rollback_implicit(thd);
11670 6 cleanup();
11671
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 });
11672
11673
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 34 times.
126 if (is_load) {
11674
2/4
✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
93 if (DBUG_EVALUATE_IF("sim_secload_fail",
11675 (my_error(ER_SECONDARY_ENGINE, MYF(0),
11676 "Simulated failure of secondary_load()"),
11677 true),
11678
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 91 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 87 times.
184 false) ||
11679
3/4
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 87 times.
91 secondary_engine_load_table(thd, *table_list->table))
11680 5 return true;
11681 } else {
11682
2/4
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
35 if (DBUG_EVALUATE_IF("sim_secunload_fail",
11683 (my_error(ER_SECONDARY_ENGINE, MYF(0),
11684 "Simulated failure of secondary_unload()"),
11685 true),
11686
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 33 times.
68 false) ||
11687
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 33 times.
33 secondary_engine_unload_table(thd, table_list->db,
11688 table_list->table_name, *table_def, true))
11689 1 return true;
11690 }
11691
11692 // Need to upgrade to allow old table definition to be purged from TDC
11693 // (this is no-op in case of SECONDARY_UNLOAD).
11694
2/4
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
120 DEBUG_SYNC(thd, "secload_upgrade_mdl_x");
11695
2/4
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 120 times.
120 if (thd->mdl_context.upgrade_shared_lock(mdl_ticket, SECLOAD_TDC_EVICT_MDL,
11696 thd->variables.lock_wait_timeout))
11697 return true;
11698
11699 // Update the secondary_load flag based on the current operation.
11700
6/14
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 120 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 120 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 120 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 120 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
240 if (table_def->options().set("secondary_load", is_load) ||
11701
2/4
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 120 times.
120 thd->dd_client()->update(table_def))
11702 return true;
11703
11704 // Close primary table.
11705
1/2
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
120 close_all_tables_for_name(thd, table_list->table->s, false, nullptr);
11706 120 table_list->table = nullptr;
11707
11708 // Commit transaction if no errors.
11709
5/10
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 120 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 120 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 120 times.
120 if (trans_commit_stmt(thd) || trans_commit_implicit(thd)) return true;
11710
11711 // Transaction committed successfully, no rollback will be necessary.
11712 120 rollback_guard.commit();
11713
11714
2/4
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 120 times.
120 if (cleanup()) return true;
11715
11716
1/2
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
120 my_ok(thd);
11717 120 return false;
11718 133 }
11719
11720 /**
11721 Check if key is a candidate key, i.e. a unique index with no index
11722 fields partial, nullable or virtual generated.
11723 */
11724
11725 34417 static bool is_candidate_key(KEY *key) {
11726 KEY_PART_INFO *key_part;
11727 34417 KEY_PART_INFO *key_part_end = key->key_part + key->user_defined_key_parts;
11728
11729
4/4
✓ Branch 0 taken 14074 times.
✓ Branch 1 taken 20343 times.
✓ Branch 2 taken 10991 times.
✓ Branch 3 taken 3083 times.
34417 if (!(key->flags & HA_NOSAME) || (key->flags & HA_NULL_PART_KEY))
11730 31334 return false;
11731
11732
2/2
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 2929 times.
3083 if (key->flags & HA_VIRTUAL_GEN_KEY) return false;
11733
11734
2/2
✓ Branch 0 taken 2997 times.
✓ Branch 1 taken 2920 times.
5917 for (key_part = key->key_part; key_part < key_part_end; key_part++) {
11735
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2988 times.
2997 if (key_part->key_part_flag & HA_PART_KEY_SEG) return false;
11736 }
11737
11738 2920 return true;
11739 }
11740
11741 /**
11742 Get Create_field object for newly created table by field index.
11743
11744 @param alter_info Alter_info describing newly created table.
11745 @param idx Field index.
11746 */
11747
11748 2072259 static const Create_field *get_field_by_index(Alter_info *alter_info,
11749 uint idx) {
11750
1/2
✓ Branch 0 taken 2072259 times.
✗ Branch 1 not taken.
2072259 List_iterator_fast<Create_field> field_it(alter_info->create_list);
11751 2072259 uint field_idx = 0;
11752 const Create_field *field;
11753
11754
5/6
✓ Branch 0 taken 11878920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9806661 times.
✓ Branch 3 taken 2072259 times.
✓ Branch 4 taken 9806661 times.
✓ Branch 5 taken 2072259 times.
11878920 while ((field = field_it++) && field_idx < idx) {
11755 9806661 field_idx++;
11756 }
11757
11758 2072259 return field;
11759 }
11760
11761 /**
11762 Look-up KEY object by index name using case-insensitive comparison.
11763
11764 @param key_name Index name.
11765 @param key_start Start of array of KEYs for table.
11766 @param key_end End of array of KEYs for table.
11767
11768 @note Skips indexes which are marked as renamed.
11769 @note Case-insensitive comparison is necessary to correctly
11770 handle renaming of keys.
11771
11772 @retval non-NULL - pointer to KEY object for index found.
11773 @retval NULL - no index with such name found (or it is marked
11774 as renamed).
11775 */
11776
11777 430 static KEY *find_key_ci(const char *key_name, KEY *key_start, KEY *key_end) {
11778
2/2
✓ Branch 0 taken 702 times.
✓ Branch 1 taken 2 times.
704 for (KEY *key = key_start; key < key_end; key++) {
11779 /* Skip already renamed keys. */
11780
4/4
✓ Branch 0 taken 700 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 428 times.
✓ Branch 3 taken 274 times.
1402 if (!(key->flags & HA_KEY_RENAMED) &&
11781
2/2
✓ Branch 0 taken 428 times.
✓ Branch 1 taken 272 times.
700 !my_strcasecmp(system_charset_info, key_name, key->name))
11782 428 return key;
11783 }
11784 2 return nullptr;
11785 }
11786
11787 /**
11788 Look-up KEY object by index name using case-sensitive comparison.
11789
11790 @param key_name Index name.
11791 @param key_start Start of array of KEYs for table.
11792 @param key_end End of array of KEYs for table.
11793
11794 @note Skips indexes which are marked as renamed.
11795 @note Case-sensitive comparison is necessary to correctly
11796 handle: ALTER TABLE t1 DROP KEY x, ADD KEY X(c).
11797 where new and old index are identical except case
11798 of their names (in this case index still needs
11799 to be re-created to keep case of the name in .FRM
11800 and storage-engine in sync).
11801
11802 @retval non-NULL - pointer to KEY object for index found.
11803 @retval NULL - no index with such name found (or it is marked
11804 as renamed).
11805 */
11806
11807 163612 static KEY *find_key_cs(const char *key_name, KEY *key_start, KEY *key_end) {
11808
2/2
✓ Branch 0 taken 231073 times.
✓ Branch 1 taken 18404 times.
249477 for (KEY *key = key_start; key < key_end; key++) {
11809 /* Skip renamed keys. */
11810
4/4
✓ Branch 0 taken 230932 times.
✓ Branch 1 taken 141 times.
✓ Branch 2 taken 145208 times.
✓ Branch 3 taken 85724 times.
231073 if (!(key->flags & HA_KEY_RENAMED) && !strcmp(key_name, key->name))
11811 145208 return key;
11812 }
11813 18404 return nullptr;
11814 }
11815
11816 /**
11817 Check if index has changed in a new version of table (ignore
11818 possible rename of index). Also changes to the comment field
11819 of the key is marked with a flag in the ha_alter_info.
11820
11821 @param[in,out] ha_alter_info Structure describing changes to be done
11822 by ALTER TABLE and holding data used
11823 during in-place alter.
11824 @param table_key Description of key in old version of table.
11825 @param new_key Description of key in new version of table.
11826
11827 @returns True - if index has changed, false -otherwise.
11828 */
11829
11830 72719 static bool has_index_def_changed(Alter_inplace_info *ha_alter_info,
11831 const KEY *table_key, const KEY *new_key) {
11832 const KEY_PART_INFO *key_part, *new_part, *end;
11833 const Create_field *new_field;
11834 72719 Alter_info *alter_info = ha_alter_info->alter_info;
11835
11836 /* Check that the key types are compatible between old and new tables. */
11837
2/2
✓ Branch 0 taken 72718 times.
✓ Branch 1 taken 1 times.
72719 if ((table_key->algorithm != new_key->algorithm) ||
11838 72718 ((table_key->flags & HA_KEYFLAG_MASK) !=
11839
2/2
✓ Branch 0 taken 72681 times.
✓ Branch 1 taken 37 times.
72718 (new_key->flags & HA_KEYFLAG_MASK)) ||
11840
2/2
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 72528 times.
72681 (table_key->user_defined_key_parts != new_key->user_defined_key_parts))
11841 191 return true;
11842
11843 /*
11844 If an index comment is added/dropped/changed, then mark it for a
11845 fast/INPLACE alteration.
11846 */
11847
2/2
✓ Branch 0 taken 72519 times.
✓ Branch 1 taken 9 times.
72528 if ((table_key->comment.length != new_key->comment.length) ||
11848
2/2
✓ Branch 0 taken 231 times.
✓ Branch 1 taken 72288 times.
72519 (table_key->comment.length &&
11849
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 227 times.
231 strcmp(table_key->comment.str, new_key->comment.str)))
11850 13 ha_alter_info->handler_flags |= Alter_inplace_info::ALTER_INDEX_COMMENT;
11851
11852 /*
11853 Check that the key parts remain compatible between the old and
11854 new tables.
11855 */
11856 72528 end = table_key->key_part + table_key->user_defined_key_parts;
11857 72528 for (key_part = table_key->key_part, new_part = new_key->key_part;
11858
2/2
✓ Branch 0 taken 113394 times.
✓ Branch 1 taken 70019 times.
183413 key_part < end; key_part++, new_part++) {
11859 113394 new_field = get_field_by_index(alter_info, new_part->fieldnr);
11860
11861 /*
11862 If there is a change in index length due to column expansion
11863 like varchar(X) changed to varchar(X + N) and has a compatible
11864 packed data representation, we mark it for fast/INPLACE change
11865 in index definition. Some engines like InnoDB supports INPLACE
11866 alter for such cases.
11867
11868 In other cases, key definition has changed if we are using a
11869 different field or if the used key part length is different, or
11870 key part direction has changed.
11871 */
11872 229202 if (key_part->length != new_part->length &&
11873
6/6
✓ Branch 0 taken 2414 times.
✓ Branch 1 taken 110980 times.
✓ Branch 2 taken 1441 times.
✓ Branch 3 taken 973 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 113378 times.
114835 ha_alter_info->alter_info->flags == Alter_info::ALTER_CHANGE_COLUMN &&
11874
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1425 times.
1441 (key_part->field->is_equal(new_field) == IS_EQUAL_PACK_LENGTH)) {
11875 16 ha_alter_info->handler_flags |=
11876 Alter_inplace_info::ALTER_COLUMN_INDEX_LENGTH;
11877
2/2
✓ Branch 0 taken 2398 times.
✓ Branch 1 taken 110980 times.
113378 } else if (key_part->length != new_part->length)
11878 2398 return true;
11879
11880 110996 if ((key_part->key_part_flag & HA_REVERSE_SORT) !=
11881
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 110984 times.
110996 (new_part->key_part_flag & HA_REVERSE_SORT))
11882 12 return true;
11883
11884 /*
11885 For prefix keys KEY_PART_INFO::field points to cloned Field
11886 object with adjusted length. So below we have to check field
11887 indexes instead of simply comparing pointers to Field objects.
11888 */
11889
4/4
✓ Branch 0 taken 110958 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 110888 times.
221942 if (!new_field->field ||
11890
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 110888 times.
110958 new_field->field->field_index() != key_part->fieldnr - 1)
11891 96 return true;
11892
11893 /*
11894 Key definition has changed, if the key is converted from a
11895 non-prefixed key to a prefixed key or vice-versa. This
11896 is because InnoDB treats prefix keys differently from
11897 full-column keys. Ignoring BLOBs since the key_length()
11898 is not set correctly and also the prefix is ignored
11899 for FULLTEXT keys.
11900 Ex: When the column length is increased but the key part
11901 length remains the same.
11902 */
11903
2/2
✓ Branch 0 taken 107652 times.
✓ Branch 1 taken 3236 times.
110888 if (!(new_field->flags & BLOB_FLAG) &&
11904
2/2
✓ Branch 0 taken 106625 times.
✓ Branch 1 taken 1027 times.
107652 (table_key->algorithm != HA_KEY_ALG_FULLTEXT)) {
11905 106625 bool old_part_key_seg = (key_part->key_part_flag & HA_PART_KEY_SEG);
11906 106625 bool new_part_key_seg = (new_field->key_length() != new_part->length);
11907
11908
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 106622 times.
106625 if (old_part_key_seg ^ new_part_key_seg) return true;
11909 }
11910 }
11911
11912 70019 return false;
11913 }
11914
11915 /**
11916 Compare original and new versions of a table and fill Alter_inplace_info
11917 describing differences between those versions.
11918
11919 @param thd Thread
11920 @param table The original table.
11921 @param[in,out] ha_alter_info Data structure which already contains
11922 basic information about create options,
11923 field and keys for the new version of
11924 table and which should be completed with
11925 more detailed information needed for
11926 in-place ALTER.
11927
11928 First argument 'table' contains information of the original
11929 table, which includes all corresponding parts that the new
11930 table has in arguments create_list, key_list and create_info.
11931
11932 Compare the changes between the original and new table definitions.
11933 The result of this comparison is then passed to SE which determines
11934 whether it can carry out these changes in-place.
11935
11936 Mark any changes detected in the ha_alter_flags.
11937 We generally try to specify handler flags only if there are real
11938 changes. But in cases when it is cumbersome to determine if some
11939 attribute has really changed we might choose to set flag
11940 pessimistically, for example, relying on parser output only.
11941
11942 If there are no data changes, but index changes, 'index_drop_buffer'
11943 and/or 'index_add_buffer' are populated with offsets into
11944 table->key_info or key_info_buffer respectively for the indexes
11945 that need to be dropped and/or (re-)created.
11946
11947 Note that this function assumes that it is OK to change Alter_info
11948 and HA_CREATE_INFO which it gets. It is caller who is responsible
11949 for creating copies for this structures if he needs them unchanged.
11950
11951 @retval true error
11952 @retval false success
11953 */
11954
11955 74915 static bool fill_alter_inplace_info(THD *thd, TABLE *table,
11956 Alter_inplace_info *ha_alter_info) {
11957 Field **f_ptr, *field;
11958 74915 List_iterator_fast<Create_field> new_field_it;
11959 Create_field *new_field;
11960 74915 uint candidate_key_count = 0;
11961 74915 Alter_info *alter_info = ha_alter_info->alter_info;
11962 74915 Prealloced_array<Field *, 1> gcols_with_unchanged_expr(PSI_INSTRUMENT_ME);
11963 // Names of columns which default might have changed.
11964 74915 Prealloced_array<const char *, 1> cols_with_default_change(PSI_INSTRUMENT_ME);
11965 // Old table version columns which were renamed or dropped.
11966 74915 Prealloced_array<const Field *, 1> dropped_or_renamed_cols(PSI_INSTRUMENT_ME);
11967
1/2
✓ Branch 0 taken 74915 times.
✗ Branch 1 not taken.
74915 DBUG_TRACE;
11968
11969 /* Allocate result buffers. */
11970 149830 if (!(ha_alter_info->index_drop_buffer =
11971
1/2
✓ Branch 0 taken 74915 times.
✗ Branch 1 not taken.
74915 (KEY **)thd->alloc(sizeof(KEY *) * table->s->keys)) ||
11972 74915 !(ha_alter_info->index_add_buffer =
11973
2/4
✓ Branch 0 taken 74915 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74915 times.
✗ Branch 3 not taken.
74915 (uint *)thd->alloc(sizeof(uint) * alter_info->key_list.size())) ||
11974
2/4
✓ Branch 0 taken 74915 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74915 times.
✗ Branch 3 not taken.
74915 !(ha_alter_info->index_rename_buffer = (KEY_PAIR *)thd->alloc(
11975
2/4
✓ Branch 0 taken 74915 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 74915 times.
224745 sizeof(KEY_PAIR) * alter_info->alter_rename_key_list.size())) ||
11976
2/4
✓ Branch 0 taken 74915 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 74915 times.
74915 !(ha_alter_info->index_altered_visibility_buffer = (KEY_PAIR *)thd->alloc(
11977 74915 sizeof(KEY_PAIR) * alter_info->alter_index_visibility_list.size())))
11978 return true;
11979
11980 /* First we setup ha_alter_flags based on what was detected by parser. */
11981
11982 /*
11983 Comparing new and old default values of column is cumbersome.
11984 So instead of using such a comparison for detecting if default
11985 has really changed we rely on flags set by parser to get an
11986 approximate value for storage engine flag.
11987 */
11988
2/2
✓ Branch 0 taken 17140 times.
✓ Branch 1 taken 57775 times.
74915 if (alter_info->flags & (Alter_info::ALTER_CHANGE_COLUMN |
11989 Alter_info::ALTER_CHANGE_COLUMN_DEFAULT))
11990 17140 ha_alter_info->handler_flags |= Alter_inplace_info::ALTER_COLUMN_DEFAULT;
11991
2/2
✓ Branch 0 taken 181 times.
✓ Branch 1 taken 74734 times.
74915 if (alter_info->flags & Alter_info::ADD_FOREIGN_KEY)
11992 181 ha_alter_info->handler_flags |= Alter_inplace_info::ADD_FOREIGN_KEY;
11993
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 74858 times.
74915 if (alter_info->flags & Alter_info::DROP_FOREIGN_KEY)
11994 57 ha_alter_info->handler_flags |= Alter_inplace_info::DROP_FOREIGN_KEY;
11995
2/2
✓ Branch 0 taken 27166 times.
✓ Branch 1 taken 47749 times.
74915 if (alter_info->flags & Alter_info::ALTER_OPTIONS)
11996 27166 ha_alter_info->handler_flags |= Alter_inplace_info::CHANGE_CREATE_OPTION;
11997
2/2
✓ Branch 0 taken 259 times.
✓ Branch 1 taken 74656 times.
74915 if (alter_info->flags & Alter_info::ALTER_RENAME)
11998 259 ha_alter_info->handler_flags |= Alter_inplace_info::ALTER_RENAME;
11999 /* Check partition changes */
12000
2/2
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 74629 times.
74915 if (alter_info->flags & Alter_info::ALTER_ADD_PARTITION)
12001 286 ha_alter_info->handler_flags |= Alter_inplace_info::ADD_PARTITION;
12002
2/2
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 74629 times.
74915 if (alter_info->flags & Alter_info::ALTER_DROP_PARTITION)
12003 286 ha_alter_info->handler_flags |= Alter_inplace_info::DROP_PARTITION;
12004
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74915 times.
74915 if (alter_info->flags & Alter_info::ALTER_PARTITION)
12005 ha_alter_info->handler_flags |= Alter_inplace_info::ALTER_PARTITION;
12006
2/2
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 74760 times.
74915 if (alter_info->flags & Alter_info::ALTER_COALESCE_PARTITION)
12007 155 ha_alter_info->handler_flags |= Alter_inplace_info::COALESCE_PARTITION;
12008
2/2
✓ Branch 0 taken 228 times.
✓ Branch 1 taken 74687 times.
74915 if (alter_info->flags & Alter_info::ALTER_REORGANIZE_PARTITION)
12009 228 ha_alter_info->handler_flags |= Alter_inplace_info::REORGANIZE_PARTITION;
12010
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 74914 times.
74915 if (alter_info->flags & Alter_info::ALTER_TABLE_REORG)
12011 1 ha_alter_info->handler_flags |= Alter_inplace_info::ALTER_TABLE_REORG;
12012
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74915 times.
74915 if (alter_info->flags & Alter_info::ALTER_REMOVE_PARTITIONING)
12013 ha_alter_info->handler_flags |=
12014 Alter_inplace_info::ALTER_REMOVE_PARTITIONING;
12015
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 74909 times.
74915 if (alter_info->flags & Alter_info::ALTER_ALL_PARTITION)
12016 6 ha_alter_info->handler_flags |= Alter_inplace_info::ALTER_ALL_PARTITION;
12017
2/2
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 74801 times.
74915 if (alter_info->flags & Alter_info::ALTER_REBUILD_PARTITION)
12018 114 ha_alter_info->handler_flags |=
12019 Alter_inplace_info::ALTER_REBUILD_PARTITION; /* purecov: deadcode */
12020 /* Check for: ALTER TABLE FORCE, ALTER TABLE ENGINE and OPTIMIZE TABLE. */
12021
2/2
✓ Branch 0 taken 5192 times.
✓ Branch 1 taken 69723 times.
74915 if (alter_info->flags & Alter_info::ALTER_RECREATE)
12022 5192 ha_alter_info->handler_flags |= Alter_inplace_info::RECREATE_TABLE;
12023
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 74901 times.
74915 if (alter_info->with_validation == Alter_info::ALTER_WITH_VALIDATION)
12024 14 ha_alter_info->handler_flags |= Alter_inplace_info::VALIDATE_VIRTUAL_COLUMN;
12025
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 74904 times.
74915 if (alter_info->flags & Alter_info::ADD_CHECK_CONSTRAINT)
12026 11 ha_alter_info->handler_flags |= Alter_inplace_info::ADD_CHECK_CONSTRAINT;
12027
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 74887 times.
74915 if (alter_info->flags & Alter_info::DROP_CHECK_CONSTRAINT)
12028 28 ha_alter_info->handler_flags |= Alter_inplace_info::DROP_CHECK_CONSTRAINT;
12029
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 74803 times.
74915 if (alter_info->flags & Alter_info::SUSPEND_CHECK_CONSTRAINT)
12030 112 ha_alter_info->handler_flags |=
12031 Alter_inplace_info::SUSPEND_CHECK_CONSTRAINT;
12032
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 74898 times.
74915 if (alter_info->flags & Alter_info::ALTER_COLUMN_VISIBILITY)
12033 17 ha_alter_info->handler_flags |= Alter_inplace_info::ALTER_COLUMN_VISIBILITY;
12034
12035 /*
12036 Go through fields in old version of table and detect changes to them.
12037 We don't want to rely solely on Alter_info flags for this since:
12038 a) new definition of column can be fully identical to the old one
12039 despite the fact that this column is mentioned in MODIFY clause.
12040 b) even if new column type differs from its old column from metadata
12041 point of view, it might be identical from storage engine point
12042 of view (e.g. when ENUM('a','b') is changed to ENUM('a','b',c')).
12043 c) flags passed to storage engine contain more detailed information
12044 about nature of changes than those provided from parser.
12045 */
12046 74915 uint old_field_index_without_vgc = 0;
12047
2/2
✓ Branch 0 taken 653683 times.
✓ Branch 1 taken 74915 times.
728598 for (f_ptr = table->field; (field = *f_ptr); f_ptr++) {
12048
5/8
✓ Branch 0 taken 653683 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 653683 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 653681 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
653683 DBUG_PRINT("inplace", ("Existing field: %s", field->field_name));
12049
12050 /* Clear marker for renamed or dropped field
12051 which we are going to set later. */
12052 653683 field->clear_flag(FIELD_IS_RENAMED);
12053 653683 field->clear_flag(FIELD_IS_DROPPED);
12054
12055 /* Use transformed info to evaluate flags for storage engine. */
12056 653683 uint new_field_index = 0;
12057 653683 uint new_field_index_without_vgc = 0;
12058 653683 new_field_it.init(alter_info->create_list);
12059
2/2
✓ Branch 0 taken 14885957 times.
✓ Branch 1 taken 2558 times.
14888515 while ((new_field = new_field_it++)) {
12060
2/2
✓ Branch 0 taken 651125 times.
✓ Branch 1 taken 14234832 times.
14885957 if (new_field->field == field) break;
12061
2/2
✓ Branch 0 taken 14076665 times.
✓ Branch 1 taken 158167 times.
14234832 if (new_field->stored_in_db) new_field_index_without_vgc++;
12062 14234832 new_field_index++;
12063 }
12064
12065
2/2
✓ Branch 0 taken 651125 times.
✓ Branch 1 taken 2558 times.
653683 if (new_field) {
12066 /* Field is not dropped. Evaluate changes bitmap for it. */
12067
12068 /*
12069 Check if type of column has changed to some incompatible type.
12070 */
12071
4/6
✓ Branch 0 taken 651125 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4801 times.
✓ Branch 3 taken 645866 times.
✓ Branch 4 taken 458 times.
✗ Branch 5 not taken.
651125 switch (field->is_equal(new_field)) {
12072 4801 case IS_EQUAL_NO:
12073
3/10
✓ Branch 0 taken 4801 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4801 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4801 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
4801 DBUG_PRINT("inplace", ("Field %s: IS_EQUAL_NO for '%s'",
12074 field->field_name, thd->query().str));
12075 /* New column type is incompatible with old one. */
12076
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4789 times.
4801 if (field->is_virtual_gcol())
12077 12 ha_alter_info->handler_flags |=
12078 Alter_inplace_info::ALTER_VIRTUAL_COLUMN_TYPE;
12079 else
12080 4789 ha_alter_info->handler_flags |=
12081 Alter_inplace_info::ALTER_STORED_COLUMN_TYPE;
12082 4801 break;
12083 645866 case IS_EQUAL_YES:
12084 /*
12085 New column is the same as the old one or the fully compatible with
12086 it (for example, ENUM('a','b') was changed to ENUM('a','b','c')).
12087 Such a change if any can ALWAYS be carried out by simply updating
12088 data-dictionary without even informing storage engine.
12089 No flag is set in this case.
12090 */
12091 645866 break;
12092 458 case IS_EQUAL_PACK_LENGTH:
12093 /*
12094 New column type differs from the old one, but has compatible packed
12095 data representation. Depending on storage engine, such a change can
12096 be carried out by simply updating data dictionary without changing
12097 actual data (for example, VARCHAR(300) is changed to VARCHAR(400)).
12098
12099 If the collation has changed, and there is an index on the column,
12100 we must mark this as a change in stored column type, which is
12101 usually rejected as inplace operation by the SE.
12102 */
12103
3/4
✓ Branch 0 taken 458 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 328 times.
✓ Branch 3 taken 130 times.
458 if (is_collation_change_for_indexed_field(*field, *new_field,
12104 ha_alter_info)) {
12105 328 ha_alter_info->handler_flags |=
12106 Alter_inplace_info::ALTER_STORED_COLUMN_TYPE;
12107 } else {
12108 130 ha_alter_info->handler_flags |=
12109 Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH;
12110 }
12111 458 break;
12112 default:
12113 assert(0);
12114 }
12115
12116 // Conversion to and from generated column is supported if stored:
12117
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 651124 times.
651125 if (field->is_gcol() != new_field->is_gcol()) {
12118
3/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 assert((field->is_gcol() && !field->is_virtual_gcol()) ||
12119 (new_field->is_gcol() && !new_field->is_virtual_gcol()));
12120 1 ha_alter_info->handler_flags |=
12121 Alter_inplace_info::ALTER_STORED_COLUMN_TYPE;
12122 }
12123
12124 // Modification of generation expression is supported:
12125
5/6
✓ Branch 0 taken 6273 times.
✓ Branch 1 taken 644852 times.
✓ Branch 2 taken 6273 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6273 times.
✓ Branch 5 taken 644852 times.
651125 if (field->is_gcol() && new_field->is_gcol()) {
12126 // Modification of storage attribute is not supported
12127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6273 times.
6273 assert(field->is_virtual_gcol() == new_field->is_virtual_gcol());
12128
3/4
✓ Branch 0 taken 6273 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 6246 times.
6273 if (!field->gcol_expr_is_equal(new_field)) {
12129
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 2 times.
27 if (field->is_virtual_gcol())
12130 25 ha_alter_info->handler_flags |=
12131 Alter_inplace_info::ALTER_VIRTUAL_GCOL_EXPR;
12132 else
12133 2 ha_alter_info->handler_flags |=
12134 Alter_inplace_info::ALTER_STORED_GCOL_EXPR;
12135 } else {
12136
1/2
✓ Branch 0 taken 6246 times.
✗ Branch 1 not taken.
6246 gcols_with_unchanged_expr.push_back(field);
12137 }
12138 }
12139
12140 bool field_renamed;
12141 /*
12142 InnoDB data dictionary is case sensitive so we should use
12143 string case sensitive comparison between fields.
12144 Note: strcmp branch is to be removed in future when we fix it
12145 in InnoDB.
12146 */
12147
2/2
✓ Branch 0 taken 114089 times.
✓ Branch 1 taken 537036 times.
651125 if (ha_alter_info->create_info->db_type->db_type == DB_TYPE_INNODB ||
12148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114089 times.
114089 ha_alter_info->create_info->db_type->db_type == DB_TYPE_NDBCLUSTER)
12149 537036 field_renamed = strcmp(field->field_name, new_field->field_name);
12150 else
12151
1/2
✓ Branch 0 taken 114089 times.
✗ Branch 1 not taken.
114089 field_renamed = my_strcasecmp(system_charset_info, field->field_name,
12152 new_field->field_name);
12153
12154 /* Check if field was renamed */
12155
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 650737 times.
651125 if (field_renamed) {
12156 388 field->set_flag(FIELD_IS_RENAMED);
12157
1/2
✓ Branch 0 taken 388 times.
✗ Branch 1 not taken.
388 dropped_or_renamed_cols.push_back(field);
12158 388 ha_alter_info->handler_flags |= Alter_inplace_info::ALTER_COLUMN_NAME;
12159 }
12160
12161 /* Check that NULL behavior is same for old and new fields */
12162
2/2
✓ Branch 0 taken 1320 times.
✓ Branch 1 taken 649805 times.
1302250 if (Overlaps(new_field->flags, NOT_NULL_FLAG) !=
12163 651125 field->is_flag_set(NOT_NULL_FLAG)) {
12164
2/2
✓ Branch 0 taken 416 times.
✓ Branch 1 taken 904 times.
1320 if (new_field->flags & NOT_NULL_FLAG)
12165 416 ha_alter_info->handler_flags |=
12166 Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE;
12167 else
12168 904 ha_alter_info->handler_flags |=
12169 Alter_inplace_info::ALTER_COLUMN_NULLABLE;
12170 }
12171
12172 /*
12173 We do not detect changes to default values in this loop.
12174 See comment above for more details.
12175 */
12176
12177 /*
12178 Detect changes in column order.
12179
12180 Note that a stored column can't become virtual and vice versa
12181 thanks to check in mysql_prepare_alter_table().
12182 */
12183
2/2
✓ Branch 0 taken 645572 times.
✓ Branch 1 taken 5553 times.
651125 if (field->stored_in_db) {
12184
2/2
✓ Branch 0 taken 5832 times.
✓ Branch 1 taken 639740 times.
645572 if (old_field_index_without_vgc != new_field_index_without_vgc)
12185 5832 ha_alter_info->handler_flags |=
12186 Alter_inplace_info::ALTER_STORED_COLUMN_ORDER;
12187 } else {
12188
2/2
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 5310 times.
5553 if (field->field_index() != new_field_index)
12189 243 ha_alter_info->handler_flags |=
12190 Alter_inplace_info::ALTER_VIRTUAL_COLUMN_ORDER;
12191 }
12192
12193 /* Detect changes in storage type of column */
12194
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 651110 times.
651125 if (new_field->field_storage_type() != field->field_storage_type())
12195 15 ha_alter_info->handler_flags |=
12196 Alter_inplace_info::ALTER_COLUMN_STORAGE_TYPE;
12197
12198 /* Detect changes in column format of column */
12199
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 651091 times.
651125 if (new_field->column_format() != field->column_format())
12200 34 ha_alter_info->handler_flags |=
12201 Alter_inplace_info::ALTER_COLUMN_COLUMN_FORMAT;
12202
12203 /*
12204 Columns which were mentioned in CHANGE/MODIFY COLUMN clause might
12205 have changed their default, add their name to corresponding array.
12206 */
12207
2/2
✓ Branch 0 taken 29838 times.
✓ Branch 1 taken 621287 times.
651125 if (new_field->change)
12208
1/2
✓ Branch 0 taken 29838 times.
✗ Branch 1 not taken.
29838 cols_with_default_change.push_back(new_field->change);
12209 } else {
12210 /*
12211 Field is not present in new version of table and therefore was dropped.
12212 */
12213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2558 times.
2558 assert(alter_info->flags & Alter_info::ALTER_DROP_COLUMN);
12214
2/2
✓ Branch 0 taken 261 times.
✓ Branch 1 taken 2297 times.
2558 if (field->is_virtual_gcol()) {
12215 261 ha_alter_info->handler_flags |= Alter_inplace_info::DROP_VIRTUAL_COLUMN;
12216 261 ha_alter_info->virtual_column_drop_count++;
12217 } else
12218 2297 ha_alter_info->handler_flags |= Alter_inplace_info::DROP_STORED_COLUMN;
12219 2558 field->set_flag(FIELD_IS_DROPPED);
12220
1/2
✓ Branch 0 taken 2558 times.
✗ Branch 1 not taken.
2558 dropped_or_renamed_cols.push_back(field);
12221 }
12222
2/2
✓ Branch 0 taken 647869 times.
✓ Branch 1 taken 5814 times.
653683 if (field->stored_in_db) old_field_index_without_vgc++;
12223 }
12224
12225
2/2
✓ Branch 0 taken 10715 times.
✓ Branch 1 taken 64200 times.
74915 if (alter_info->flags & Alter_info::ALTER_ADD_COLUMN) {
12226 10715 new_field_it.init(alter_info->create_list);
12227
2/2
✓ Branch 0 taken 104841 times.
✓ Branch 1 taken 10715 times.
115556 while ((new_field = new_field_it++)) {
12228
2/2
✓ Branch 0 taken 17484 times.
✓ Branch 1 taken 87357 times.
104841 if (!new_field->field) {
12229 /*
12230 Field is not present in old version of table and therefore was added.
12231 */
12232
2/2
✓ Branch 0 taken 903 times.
✓ Branch 1 taken 16581 times.
17484 if (new_field->is_virtual_gcol()) {
12233 903 ha_alter_info->handler_flags |=
12234 Alter_inplace_info::ADD_VIRTUAL_COLUMN;
12235 903 ha_alter_info->virtual_column_add_count++;
12236
4/4
✓ Branch 0 taken 16484 times.
✓ Branch 1 taken 97 times.
✓ Branch 2 taken 101 times.
✓ Branch 3 taken 16383 times.
16581 } else if (new_field->gcol_info || new_field->m_default_val_expr)
12237 198 ha_alter_info->handler_flags |=
12238 Alter_inplace_info::ADD_STORED_GENERATED_COLUMN;
12239 else
12240 16383 ha_alter_info->handler_flags |=
12241 Alter_inplace_info::ADD_STORED_BASE_COLUMN;
12242 }
12243 }
12244 /* One of these should be set since Alter_info::ALTER_ADD_COLUMN was set. */
12245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10715 times.
10715 assert(ha_alter_info->handler_flags &
12246 (Alter_inplace_info::ADD_VIRTUAL_COLUMN |
12247 Alter_inplace_info::ADD_STORED_BASE_COLUMN |
12248 Alter_inplace_info::ADD_STORED_GENERATED_COLUMN));
12249 }
12250
12251 /*
12252 Add columns mentioned in SET/DROP DEFAULT clause to array of column names
12253 which might have changed default.
12254 */
12255
3/4
✓ Branch 0 taken 74915 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 244 times.
✓ Branch 3 taken 74915 times.
75159 for (const Alter_column *alter : alter_info->alter_list) {
12256
6/6
✓ Branch 0 taken 145 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 80 times.
✓ Branch 3 taken 65 times.
✓ Branch 4 taken 179 times.
✓ Branch 5 taken 65 times.
389 if (alter->change_type() == Alter_column::Type::SET_DEFAULT ||
12257 145 alter->change_type() == Alter_column::Type::DROP_DEFAULT) {
12258
1/2
✓ Branch 0 taken 179 times.
✗ Branch 1 not taken.
179 cols_with_default_change.push_back(alter->name);
12259 }
12260 }
12261
12262 /*
12263 Detect cases when we have generated columns that depend on columns
12264 which were swapped (by renaming them) or replaced (by dropping and
12265 then adding column with the same name). Also detect cases when
12266 generated columns depend on the DEFAULT function on a column and
12267 column default might have changed.
12268
12269 Storage engine might be unable to do such operation inplace as indexes
12270 or value of stored generated columns might become invalid and require
12271 re-evaluation by SQL-layer.
12272 */
12273
4/6
✓ Branch 0 taken 74915 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74915 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6246 times.
✓ Branch 5 taken 74915 times.
81161 for (Field *vfield : gcols_with_unchanged_expr) {
12274 6246 bool gcol_needs_reeval = false;
12275
4/6
✓ Branch 0 taken 6246 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6246 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 601 times.
✓ Branch 5 taken 6246 times.
6847 for (const char *col_name : cols_with_default_change) {
12276
2/4
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 601 times.
601 if (vfield->gcol_info->expr_item->walk(
12277 &Item::check_gcol_depend_default_processor, enum_walk::POSTFIX,
12278 reinterpret_cast<uchar *>(const_cast<char *>(col_name)))) {
12279 gcol_needs_reeval = true;
12280 break;
12281 }
12282 }
12283
12284
6/8
✓ Branch 0 taken 6246 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6246 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 697 times.
✓ Branch 5 taken 5549 times.
✓ Branch 6 taken 697 times.
✓ Branch 7 taken 5549 times.
6246 if (!gcol_needs_reeval && !dropped_or_renamed_cols.empty()) {
12285 697 MY_BITMAP dependent_fields;
12286 my_bitmap_map
12287 bitbuf[bitmap_buffer_size(MAX_FIELDS) / sizeof(my_bitmap_map)];
12288
1/2
✓ Branch 0 taken 697 times.
✗ Branch 1 not taken.
697 bitmap_init(&dependent_fields, bitbuf, table->s->fields);
12289 697 MY_BITMAP *save_old_read_set = table->read_set;
12290 697 table->read_set = &dependent_fields;
12291 697 Mark_field mark_fld(MARK_COLUMNS_TEMP);
12292
1/2
✓ Branch 0 taken 697 times.
✗ Branch 1 not taken.
697 vfield->gcol_info->expr_item->walk(&Item::mark_field_in_map,
12293 enum_walk::PREFIX,
12294 reinterpret_cast<uchar *>(&mark_fld));
12295
4/6
✓ Branch 0 taken 697 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 697 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 709 times.
✓ Branch 5 taken 697 times.
1406 for (const Field *dr_field : dropped_or_renamed_cols) {
12296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 709 times.
709 if (bitmap_is_set(table->read_set, dr_field->field_index())) {
12297 gcol_needs_reeval = true;
12298 break;
12299 }
12300 }
12301 697 table->read_set = save_old_read_set;
12302 }
12303
12304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6246 times.
6246 if (gcol_needs_reeval) {
12305 if (vfield->is_virtual_gcol())
12306 ha_alter_info->handler_flags |= Alter_inplace_info::VIRTUAL_GCOL_REEVAL;
12307 else
12308 ha_alter_info->handler_flags |= Alter_inplace_info::STORED_GCOL_REEVAL;
12309 }
12310
12311 /*
12312 Stop our search early if flags indicating re-evaluation of both
12313 virtual and stored generated columns are already set.
12314 */
12315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6246 times.
6246 if ((ha_alter_info->handler_flags &
12316 (Alter_inplace_info::VIRTUAL_GCOL_REEVAL |
12317 Alter_inplace_info::STORED_GCOL_REEVAL)) ==
12318 (Alter_inplace_info::VIRTUAL_GCOL_REEVAL |
12319 Alter_inplace_info::STORED_GCOL_REEVAL))
12320 break;
12321 }
12322
12323 /*
12324 Go through keys and check if the original ones are compatible
12325 with new table.
12326 */
12327 KEY *table_key;
12328 74915 KEY *table_key_end = table->key_info + table->s->keys;
12329 KEY *new_key;
12330 74915 KEY *new_key_end = ha_alter_info->key_info_buffer + ha_alter_info->key_count;
12331
12332
5/8
✓ Branch 0 taken 74915 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74915 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 74913 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
74915 DBUG_PRINT("info", ("index count old: %d new: %d", table->s->keys,
12333 ha_alter_info->key_count));
12334
12335 /*
12336 First, we need to handle keys being renamed, otherwise code handling
12337 dropping/addition of keys might be confused in some situations.
12338 */
12339
2/2
✓ Branch 0 taken 78529 times.
✓ Branch 1 taken 74915 times.
153444 for (table_key = table->key_info; table_key < table_key_end; table_key++)
12340 78529 table_key->flags &= ~HA_KEY_RENAMED;
12341
2/2
✓ Branch 0 taken 85315 times.
✓ Branch 1 taken 74915 times.
160230 for (new_key = ha_alter_info->key_info_buffer; new_key < new_key_end;
12342 new_key++)
12343 85315 new_key->flags &= ~HA_KEY_RENAMED;
12344
12345
3/4
✓ Branch 0 taken 74915 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 115 times.
✓ Branch 3 taken 74915 times.
75030 for (const Alter_rename_key *rename_key : alter_info->alter_rename_key_list) {
12346 table_key =
12347
1/2
✓ Branch 0 taken 115 times.
✗ Branch 1 not taken.
115 find_key_ci(rename_key->old_name, table->key_info, table_key_end);
12348
1/2
✓ Branch 0 taken 115 times.
✗ Branch 1 not taken.
115 new_key = find_key_ci(rename_key->new_name, ha_alter_info->key_info_buffer,
12349 new_key_end);
12350
12351 115 table_key->flags |= HA_KEY_RENAMED;
12352 115 new_key->flags |= HA_KEY_RENAMED;
12353
12354
3/4
✓ Branch 0 taken 115 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 113 times.
✓ Branch 3 taken 2 times.
115 if (!has_index_def_changed(ha_alter_info, table_key, new_key)) {
12355 /* Key was not modified in any significant way but still was renamed. */
12356 113 ha_alter_info->handler_flags |= Alter_inplace_info::RENAME_INDEX;
12357
1/2
✓ Branch 0 taken 113 times.
✗ Branch 1 not taken.
113 ha_alter_info->add_renamed_key(table_key, new_key);
12358
12359 /*
12360 Check for insignificant changes which do not call for index
12361 recreation, but still require update of .FRM.
12362 */
12363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 113 times.
113 if (table_key->is_algorithm_explicit != new_key->is_algorithm_explicit)
12364 ha_alter_info->handler_flags |= Alter_inplace_info::CHANGE_INDEX_OPTION;
12365 } else {
12366 /* Key was modified. */
12367
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 ha_alter_info->add_modified_key(table_key, new_key);
12368 }
12369 }
12370
12371 75014 for (const Alter_index_visibility *alter_index_visibility :
12372
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 74914 times.
149929 alter_info->alter_index_visibility_list) {
12373 100 const char *name = alter_index_visibility->name();
12374
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 table_key = find_key_ci(name, table->key_info, table_key_end);
12375
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 new_key = find_key_ci(name, ha_alter_info->key_info_buffer, new_key_end);
12376
12377
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 99 times.
100 if (new_key == nullptr) {
12378
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), name, table->s->table_name.str);
12379 1 return true;
12380 }
12381
12382 99 new_key->is_visible = alter_index_visibility->is_visible();
12383 99 ha_alter_info->handler_flags |= Alter_inplace_info::RENAME_INDEX;
12384
1/2
✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
99 ha_alter_info->add_altered_index_visibility(table_key, new_key);
12385 }
12386
12387 /*
12388 Step through all keys of the old table and search matching new keys.
12389 */
12390
2/2
✓ Branch 0 taken 78527 times.
✓ Branch 1 taken 74914 times.
153441 for (table_key = table->key_info; table_key < table_key_end; table_key++) {
12391 /* Skip renamed keys. */
12392
2/2
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 78413 times.
78527 if (table_key->flags & HA_KEY_RENAMED) continue;
12393
12394 78413 new_key = find_key_cs(table_key->name, ha_alter_info->key_info_buffer,
12395 new_key_end);
12396
12397
2/2
✓ Branch 0 taken 5809 times.
✓ Branch 1 taken 72604 times.
78413 if (new_key == nullptr) {
12398 /* Matching new key not found. This means the key should be dropped. */
12399
1/2
✓ Branch 0 taken 5809 times.
✗ Branch 1 not taken.
5809 ha_alter_info->add_dropped_key(table_key);
12400
3/4
✓ Branch 0 taken 72604 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2698 times.
✓ Branch 3 taken 69906 times.
72604 } else if (has_index_def_changed(ha_alter_info, table_key, new_key)) {
12401 /* Key was modified. */
12402
1/2
✓ Branch 0 taken 2698 times.
✗ Branch 1 not taken.
2698 ha_alter_info->add_modified_key(table_key, new_key);
12403 } else {
12404 /*
12405 Key was not modified in significant way. Still we need to check
12406 for insignificant changes which do not call for index recreation,
12407 but still require update of .FRM.
12408 */
12409
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 69904 times.
69906 if (table_key->is_algorithm_explicit != new_key->is_algorithm_explicit)
12410 2 ha_alter_info->handler_flags |= Alter_inplace_info::CHANGE_INDEX_OPTION;
12411 }
12412 }
12413
12414 /*
12415 Step through all keys of the new table and find matching old keys.
12416 */
12417
2/2
✓ Branch 0 taken 85313 times.
✓ Branch 1 taken 74914 times.
160227 for (new_key = ha_alter_info->key_info_buffer; new_key < new_key_end;
12418 new_key++) {
12419 /* Skip renamed keys. */
12420
2/2
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 85199 times.
85313 if (new_key->flags & HA_KEY_RENAMED) continue;
12421
12422
2/2
✓ Branch 0 taken 12595 times.
✓ Branch 1 taken 72604 times.
85199 if (!find_key_cs(new_key->name, table->key_info, table_key_end)) {
12423 /* Matching old key not found. This means the key should be added. */
12424
1/2
✓ Branch 0 taken 12595 times.
✗ Branch 1 not taken.
12595 ha_alter_info->add_added_key(new_key);
12425 }
12426 }
12427
12428 /*
12429 Sort index_add_buffer according to how key_info_buffer is sorted.
12430 I.e. with primary keys first - see sort_keys().
12431 */
12432 74914 std::sort(ha_alter_info->index_add_buffer,
12433
1/2
✓ Branch 0 taken 74914 times.
✗ Branch 1 not taken.
74914 ha_alter_info->index_add_buffer + ha_alter_info->index_add_count);
12434
12435 /* Now let us calculate flags for storage engine API. */
12436
12437 /* Count all existing candidate keys. */
12438
2/2
✓ Branch 0 taken 78527 times.
✓ Branch 1 taken 74914 times.
153441 for (table_key = table->key_info; table_key < table_key_end; table_key++) {
12439 /*
12440 Check if key is a candidate key, This key is either already primary key
12441 or could be promoted to primary key if the original primary key is
12442 dropped.
12443 In MySQL one is allowed to create primary key with partial fields (i.e.
12444 primary key which is not considered candidate). For simplicity we count
12445 such key as a candidate key here.
12446 */
12447
6/6
✓ Branch 0 taken 32544 times.
✓ Branch 1 taken 45983 times.
✓ Branch 2 taken 2886 times.
✓ Branch 3 taken 29658 times.
✓ Branch 4 taken 48869 times.
✓ Branch 5 taken 29658 times.
111071 if (((uint)(table_key - table->key_info) == table->s->primary_key) ||
12448 32544 is_candidate_key(table_key))
12449 48869 candidate_key_count++;
12450 }
12451
12452 /* Figure out what kind of indexes we are dropping. */
12453 KEY **dropped_key;
12454 74914 KEY **dropped_key_end =
12455 74914 ha_alter_info->index_drop_buffer + ha_alter_info->index_drop_count;
12456
12457 83423 for (dropped_key = ha_alter_info->index_drop_buffer;
12458
2/2
✓ Branch 0 taken 8509 times.
✓ Branch 1 taken 74914 times.
83423 dropped_key < dropped_key_end; dropped_key++) {
12459 8509 table_key = *dropped_key;
12460
12461
2/2
✓ Branch 0 taken 4316 times.
✓ Branch 1 taken 4193 times.
8509 if (table_key->flags & HA_NOSAME) {
12462 /*
12463 Unique key. Check for PRIMARY KEY. Also see comment about primary
12464 and candidate keys above.
12465 */
12466
2/2
✓ Branch 0 taken 2443 times.
✓ Branch 1 taken 1873 times.
4316 if ((uint)(table_key - table->key_info) == table->s->primary_key) {
12467 2443 ha_alter_info->handler_flags |= Alter_inplace_info::DROP_PK_INDEX;
12468 2443 candidate_key_count--;
12469 } else {
12470 1873 ha_alter_info->handler_flags |= Alter_inplace_info::DROP_UNIQUE_INDEX;
12471
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 1839 times.
1873 if (is_candidate_key(table_key)) candidate_key_count--;
12472 }
12473 } else
12474 4193 ha_alter_info->handler_flags |= Alter_inplace_info::DROP_INDEX;
12475 }
12476
12477 /* Now figure out what kind of indexes we are adding. */
12478
2/2
✓ Branch 0 taken 15295 times.
✓ Branch 1 taken 74914 times.
90209 for (uint add_key_idx = 0; add_key_idx < ha_alter_info->index_add_count;
12479 add_key_idx++) {
12480 15295 new_key = ha_alter_info->key_info_buffer +
12481 15295 ha_alter_info->index_add_buffer[add_key_idx];
12482
12483
2/2
✓ Branch 0 taken 6387 times.
✓ Branch 1 taken 8908 times.
15295 if (new_key->flags & HA_NOSAME) {
12484 bool is_pk =
12485
1/2
✓ Branch 0 taken 6387 times.
✗ Branch 1 not taken.
6387 !my_strcasecmp(system_charset_info, new_key->name, primary_key_name);
12486
12487
2/2
✓ Branch 0 taken 6116 times.
✓ Branch 1 taken 271 times.
6387 if ((!(new_key->flags & HA_KEY_HAS_PART_KEY_SEG) &&
12488
4/4
✓ Branch 0 taken 2707 times.
✓ Branch 1 taken 3409 times.
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 2907 times.
6387 !(new_key->flags & HA_NULL_PART_KEY)) ||
12489 is_pk) {
12490 /* Candidate key or primary key! */
12491
4/4
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 3343 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 131 times.
3480 if (candidate_key_count == 0 || is_pk)
12492 3349 ha_alter_info->handler_flags |= Alter_inplace_info::ADD_PK_INDEX;
12493 else
12494 131 ha_alter_info->handler_flags |= Alter_inplace_info::ADD_UNIQUE_INDEX;
12495 3480 candidate_key_count++;
12496 } else {
12497 2907 ha_alter_info->handler_flags |= Alter_inplace_info::ADD_UNIQUE_INDEX;
12498 }
12499 } else {
12500
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 8800 times.
8908 if (new_key->flags & HA_SPATIAL) {
12501 108 ha_alter_info->handler_flags |= Alter_inplace_info::ADD_SPATIAL_INDEX;
12502 } else {
12503 8800 ha_alter_info->handler_flags |= Alter_inplace_info::ADD_INDEX;
12504 }
12505 }
12506 }
12507
12508 74914 return false;
12509 74915 }
12510
12511 /**
12512 Mark fields participating in newly added indexes in TABLE object which
12513 corresponds to new version of altered table.
12514
12515 @param ha_alter_info Alter_inplace_info describing in-place ALTER.
12516 @param altered_table TABLE object for new version of TABLE in which
12517 fields should be marked.
12518 */
12519
12520 74894 static void update_altered_table(const Alter_inplace_info &ha_alter_info,
12521 TABLE *altered_table) {
12522 uint field_idx, add_key_idx;
12523 KEY *key;
12524 KEY_PART_INFO *end, *key_part;
12525
12526 /*
12527 Clear marker for all fields, as we are going to set it only
12528 for fields which participate in new indexes.
12529 */
12530
2/2
✓ Branch 0 taken 668548 times.
✓ Branch 1 taken 74894 times.
743442 for (field_idx = 0; field_idx < altered_table->s->fields; ++field_idx)
12531 668548 altered_table->field[field_idx]->clear_flag(FIELD_IN_ADD_INDEX);
12532
12533 /*
12534 Go through array of newly added indexes and mark fields
12535 participating in them.
12536 */
12537
2/2
✓ Branch 0 taken 15294 times.
✓ Branch 1 taken 74894 times.
90188 for (add_key_idx = 0; add_key_idx < ha_alter_info.index_add_count;
12538 add_key_idx++) {
12539 15294 key = ha_alter_info.key_info_buffer +
12540 15294 ha_alter_info.index_add_buffer[add_key_idx];
12541
12542 15294 end = key->key_part + key->user_defined_key_parts;
12543
2/2
✓ Branch 0 taken 23291 times.
✓ Branch 1 taken 15294 times.
38585 for (key_part = key->key_part; key_part < end; key_part++)
12544 23291 altered_table->field[key_part->fieldnr]->set_flag(FIELD_IN_ADD_INDEX);
12545 }
12546 74894 }
12547
12548 /**
12549 Initialize TABLE::field for the new table with appropriate
12550 column static defaults.
12551
12552 @note Can be plain default values from TABLE_SHARE::default_values
12553 or datetime function defaults. We don't handle general
12554 expression defaults here as their values need to be evaluated
12555 for each row and such evaluation might result in error.
12556
12557 @param altered_table TABLE object for the new version of the table.
12558 @param create Create_field list for new version of the table,
12559 which is used for identifying new columns.
12560 */
12561
12562 95364 static void set_column_static_defaults(TABLE *altered_table,
12563 List<Create_field> &create) {
12564 // Initialize TABLE::field default values
12565 95364 restore_record(altered_table, s->default_values);
12566
12567 // Now set datetime expression defaults for new columns.
12568
1/2
✓ Branch 0 taken 95364 times.
✗ Branch 1 not taken.
95364 List_iterator<Create_field> iter(create);
12569
2/2
✓ Branch 0 taken 777052 times.
✓ Branch 1 taken 95364 times.
872416 for (uint i = 0; i < altered_table->s->fields; ++i) {
12570 777052 const Create_field *definition = iter++;
12571
6/6
✓ Branch 0 taken 21751 times.
✓ Branch 1 taken 755301 times.
✓ Branch 2 taken 243 times.
✓ Branch 3 taken 21508 times.
✓ Branch 4 taken 243 times.
✓ Branch 5 taken 776809 times.
798803 if (definition->field == nullptr &&
12572 21751 altered_table->field[i]->has_insert_default_datetime_value_expression())
12573
1/2
✓ Branch 0 taken 243 times.
✗ Branch 1 not taken.
243 altered_table->field[i]->evaluate_insert_default_function();
12574 }
12575 95364 }
12576
12577 /**
12578 Compare two tables to see if their metadata are compatible.
12579 One table specified by a TABLE instance, the other using Alter_info
12580 and HA_CREATE_INFO.
12581
12582 @param thd Thread handler
12583 @param[in] table The first table.
12584 @param[in] alter_info Alter options, fields and keys for the
12585 second table.
12586 @param[in] create_info Create options for the second table.
12587 @param[out] metadata_equal Result of comparison.
12588
12589 @retval true error
12590 @retval false success
12591 */
12592
12593 254 bool mysql_compare_tables(THD *thd, TABLE *table, Alter_info *alter_info,
12594 HA_CREATE_INFO *create_info, bool *metadata_equal) {
12595
1/2
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
254 DBUG_TRACE;
12596
12597 254 uint changes = IS_EQUAL_NO;
12598 uint key_count;
12599 254 uint fk_key_count = 0;
12600 254 List_iterator_fast<Create_field> tmp_new_field_it;
12601 254 *metadata_equal = false;
12602
12603 /*
12604 Create a copy of alter_info.
12605 To compare definitions, we need to "prepare" the definition - transform it
12606 from parser output to a format that describes the table layout (all column
12607 defaults are initialized, duplicate columns are removed). This is done by
12608 mysql_prepare_create_table. Unfortunately, mysql_prepare_create_table
12609 performs its transformations "in-place", that is, modifies the argument.
12610 Since we would like to keep mysql_compare_tables() idempotent (not altering
12611 any of the arguments) we create a copy of alter_info here and pass it to
12612 mysql_prepare_create_table, then use the result to compare the tables, and
12613 then destroy the copy.
12614 */
12615
1/2
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
254 Alter_info tmp_alter_info(*alter_info, thd->mem_root);
12616 254 KEY *key_info_buffer = nullptr;
12617 254 FOREIGN_KEY *fk_key_info_buffer = nullptr;
12618
12619 /* Create the prepared information. */
12620
2/4
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 254 times.
254 if (mysql_prepare_create_table(thd,
12621 "", // Not used
12622 "", // Not used
12623 create_info, &tmp_alter_info, table->file,
12624 false, // Not used
12625 &key_info_buffer, &key_count,
12626 &fk_key_info_buffer, &fk_key_count, nullptr, 0,
12627 nullptr, 0, 0, false))
12628 return true;
12629
12630 /* Some very basic checks. */
12631 761 if (table->s->fields != alter_info->create_list.elements ||
12632
7/10
✓ Branch 0 taken 253 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 253 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 253 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 253 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 253 times.
507 table->s->db_type() != create_info->db_type || table->s->tmp_table ||
12633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 253 times.
253 (table->s->row_type != create_info->row_type))
12634 1 return false;
12635
12636 /* Go through fields and check if they are compatible. */
12637 253 tmp_new_field_it.init(tmp_alter_info.create_list);
12638
2/2
✓ Branch 0 taken 618 times.
✓ Branch 1 taken 249 times.
867 for (Field **f_ptr = table->field; *f_ptr; f_ptr++) {
12639 618 Field *field = *f_ptr;
12640 618 const Create_field *tmp_new_field = tmp_new_field_it++;
12641
12642 /* Check to see if both fields are alike. */
12643
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 617 times.
618 if (tmp_new_field->is_virtual_gcol() != field->is_virtual_gcol()) {
12644
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN, MYF(0),
12645 "Exchanging partitions for non-generated columns");
12646 1 return false;
12647 }
12648
12649 /* Check that NULL behavior is the same. */
12650 1234 if ((tmp_new_field->flags & NOT_NULL_FLAG) !=
12651
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 616 times.
617 field->is_flag_set(NOT_NULL_FLAG))
12652 1 return false;
12653
12654 /* Check if field was renamed */
12655
3/4
✓ Branch 0 taken 616 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 615 times.
616 if (my_strcasecmp(system_charset_info, field->field_name,
12656 tmp_new_field->field_name))
12657 1 return false;
12658
12659 /* Evaluate changes bitmap and send to check_if_incompatible_data() */
12660
1/2
✓ Branch 0 taken 615 times.
✗ Branch 1 not taken.
615 uint field_changes = field->is_equal(tmp_new_field);
12661
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 614 times.
615 if (field_changes != IS_EQUAL_YES) return false;
12662
12663 614 changes |= field_changes;
12664 }
12665
12666 /* Check if changes are compatible with current handler. */
12667
2/4
✓ Branch 0 taken 249 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 249 times.
249 if (table->file->check_if_incompatible_data(create_info, changes))
12668 return false;
12669
12670 /* Go through keys and check if they are compatible. */
12671 KEY *table_key;
12672 249 KEY *table_key_end = table->key_info + table->s->keys;
12673 KEY *new_key;
12674 249 KEY *new_key_end = key_info_buffer + key_count;
12675
12676 /* Step through all keys of the first table and search matching keys. */
12677
2/2
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 245 times.
490 for (table_key = table->key_info; table_key < table_key_end; table_key++) {
12678 /* Search a key with the same name. */
12679
2/2
✓ Branch 0 taken 289 times.
✓ Branch 1 taken 4 times.
293 for (new_key = key_info_buffer; new_key < new_key_end; new_key++) {
12680
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 48 times.
289 if (!strcmp(table_key->name, new_key->name)) break;
12681 }
12682
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 241 times.
245 if (new_key >= new_key_end) return false;
12683
12684 /* Check that the key types are compatible. */
12685
1/2
✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
241 if ((table_key->algorithm != new_key->algorithm) ||
12686 241 ((table_key->flags & HA_KEYFLAG_MASK) !=
12687
1/2
✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
241 (new_key->flags & HA_KEYFLAG_MASK)) ||
12688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 241 times.
241 (table_key->user_defined_key_parts != new_key->user_defined_key_parts))
12689 return false;
12690
12691 /* Check that the key parts remain compatible. */
12692 KEY_PART_INFO *table_part;
12693 241 KEY_PART_INFO *table_part_end =
12694 241 table_key->key_part + table_key->user_defined_key_parts;
12695 KEY_PART_INFO *new_part;
12696 241 for (table_part = table_key->key_part, new_part = new_key->key_part;
12697
2/2
✓ Branch 0 taken 272 times.
✓ Branch 1 taken 241 times.
513 table_part < table_part_end; table_part++, new_part++) {
12698 /*
12699 Key definition is different if we are using a different field or
12700 if the used key part length is different. We know that the fields
12701 are equal. Comparing field numbers is sufficient.
12702 */
12703
1/2
✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
272 if ((table_part->length != new_part->length) ||
12704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 272 times.
272 (table_part->fieldnr - 1 != new_part->fieldnr))
12705 return false;
12706 }
12707 }
12708
12709 /* Step through all keys of the second table and find matching keys. */
12710
2/2
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 244 times.
482 for (new_key = key_info_buffer; new_key < new_key_end; new_key++) {
12711 /* Search a key with the same name. */
12712
2/2
✓ Branch 0 taken 280 times.
✓ Branch 1 taken 1 times.
281 for (table_key = table->key_info; table_key < table_key_end; table_key++) {
12713
2/2
✓ Branch 0 taken 237 times.
✓ Branch 1 taken 43 times.
280 if (!strcmp(table_key->name, new_key->name)) break;
12714 }
12715
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 237 times.
238 if (table_key >= table_key_end) return false;
12716 }
12717
12718 244 *metadata_equal = true; // Tables are compatible
12719 244 return false;
12720 254 }
12721
12722 /**
12723 Report a zero date warning if no default value is supplied
12724 for the DATE/DATETIME 'NOT NULL' field and 'NO_ZERO_DATE'
12725 sql_mode is enabled.
12726
12727 @param thd Thread handle.
12728 @param datetime_field DATE/DATETIME column definition.
12729 */
12730 11 static bool push_zero_date_warning(THD *thd, Create_field *datetime_field) {
12731 11 uint f_length = 0;
12732 11 enum enum_mysql_timestamp_type t_type = MYSQL_TIMESTAMP_DATE;
12733
12734
2/3
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
11 switch (datetime_field->sql_type) {
12735 4 case MYSQL_TYPE_DATE:
12736 case MYSQL_TYPE_NEWDATE:
12737 4 f_length = MAX_DATE_WIDTH; // "0000-00-00";
12738 4 t_type = MYSQL_TIMESTAMP_DATE;
12739 4 break;
12740 7 case MYSQL_TYPE_DATETIME:
12741 case MYSQL_TYPE_DATETIME2:
12742 7 f_length = MAX_DATETIME_WIDTH; // "0000-00-00 00:00:00";
12743 7 t_type = MYSQL_TIMESTAMP_DATETIME;
12744 7 break;
12745 default:
12746 assert(false); // Should not get here.
12747 }
12748
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 return make_truncated_value_warning(
12749 thd, Sql_condition::SL_WARNING,
12750 22 ErrConvString(my_zero_datetime6, f_length), t_type,
12751 22 datetime_field->field_name);
12752 }
12753
12754 /*
12755 Manages enabling/disabling of indexes for ALTER TABLE
12756
12757 SYNOPSIS
12758 alter_table_manage_keys()
12759 table Target table
12760 indexes_were_disabled Whether the indexes of the from table
12761 were disabled
12762 keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
12763
12764 RETURN VALUES
12765 false OK
12766 true Error
12767 */
12768
12769 20493 static bool alter_table_manage_keys(
12770 THD *thd, TABLE *table, int indexes_were_disabled,
12771 Alter_info::enum_enable_or_disable keys_onoff) {
12772 20493 int error = 0;
12773
1/2
✓ Branch 0 taken 20493 times.
✗ Branch 1 not taken.
20493 DBUG_TRACE;
12774
3/8
✓ Branch 0 taken 20493 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20493 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 20493 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
20493 DBUG_PRINT("enter", ("table=%p were_disabled=%d on_off=%d", table,
12775 indexes_were_disabled, keys_onoff));
12776
12777
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 20471 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
20493 switch (keys_onoff) {
12778 8 case Alter_info::ENABLE:
12779
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 error = table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
12780 8 break;
12781 20471 case Alter_info::LEAVE_AS_IS:
12782
2/2
✓ Branch 0 taken 20467 times.
✓ Branch 1 taken 4 times.
20471 if (!indexes_were_disabled) break;
12783 /* fall-through: disabled indexes */
12784 [[fallthrough]];
12785 case Alter_info::DISABLE:
12786
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 error = table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
12787 }
12788
12789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20493 times.
20493 if (error == HA_ERR_WRONG_COMMAND) {
12790 push_warning_printf(thd, Sql_condition::SL_NOTE, ER_ILLEGAL_HA,
12791 ER_THD(thd, ER_ILLEGAL_HA), table->s->table_name.str);
12792 error = 0;
12793
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20493 times.
20493 } else if (error)
12794 table->file->print_error(error, MYF(0));
12795
12796 20493 return error;
12797 20493 }
12798
12799 /**
12800 Check if the pending ALTER TABLE operations support the in-place
12801 algorithm based on restrictions in the SQL layer or given the
12802 nature of the operations themselves. If in-place isn't supported,
12803 it won't be necessary to check with the storage engine.
12804
12805 @param table The original TABLE.
12806 @param create_info Information from the parsing phase about new
12807 table properties.
12808 @param alter_info Data related to detected changes.
12809
12810 @return false In-place is possible, check with storage engine.
12811 @return true Incompatible operations, must use table copy.
12812 */
12813
12814 88231 static bool is_inplace_alter_impossible(TABLE *table,
12815 HA_CREATE_INFO *create_info,
12816 const Alter_info *alter_info) {
12817
1/2
✓ Branch 0 taken 88231 times.
✗ Branch 1 not taken.
88231 DBUG_TRACE;
12818
12819 /* At the moment we can't handle altering temporary tables without a copy. */
12820
2/2
✓ Branch 0 taken 1164 times.
✓ Branch 1 taken 87067 times.
88231 if (table->s->tmp_table) return true;
12821
12822 /*
12823 For the ALTER TABLE tbl_name ORDER BY ... we always use copy
12824 algorithm. In theory, this operation can be done in-place by some
12825 engine, but since a) no current engine does this and b) our current
12826 API lacks infrastructure for passing information about table ordering
12827 to storage engine we simply always do copy now.
12828
12829 ENABLE/DISABLE KEYS is a MyISAM/Heap specific operation that is
12830 not supported for in-place in combination with other operations.
12831 Alone, it will be done by simple_rename_or_index_change().
12832
12833 Stored generated columns are evaluated in server, thus can't be
12834 added/changed inplace.
12835 */
12836
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 86984 times.
87067 if (alter_info->flags &
12837 (Alter_info::ALTER_ORDER | Alter_info::ALTER_KEYS_ONOFF))
12838 83 return true;
12839
12840 /*
12841 Check constraints are evaluated in the server, if any check constraint
12842 (re-)evaluation is required then it can't be added/enforced inplace.
12843 */
12844
3/4
✓ Branch 0 taken 86984 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 124 times.
✓ Branch 3 taken 86860 times.
86984 if (is_any_check_constraints_evaluation_required(alter_info)) return true;
12845
12846 /*
12847 If the table engine is changed explicitly (using ENGINE clause)
12848 or implicitly (e.g. when non-partitioned table becomes
12849 partitioned) a regular alter table (copy) needs to be
12850 performed.
12851 */
12852
3/4
✓ Branch 0 taken 86860 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 826 times.
✓ Branch 3 taken 86034 times.
86860 if (create_info->db_type != table->s->db_type()) return true;
12853
12854 /*
12855 There was a bug prior to mysql-4.0.25. Number of null fields was
12856 calculated incorrectly. As a result frm and data files gets out of
12857 sync after fast alter table. There is no way to determine by which
12858 mysql version (in 4.0 and 4.1 branches) table was created, thus we
12859 disable fast alter table for all tables created by mysql versions
12860 prior to 5.0 branch.
12861 See BUG#6236.
12862 */
12863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86034 times.
86034 if (!table->s->mysql_version) return true;
12864
12865 /*
12866 If we are changing the SRID modifier of a column, we must do a COPY.
12867 But not if we are changing to the NULL SRID. In that case, we can do it
12868 inplace (only metadata change, and no verification needed).
12869 */
12870
5/8
✓ Branch 0 taken 86034 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 86034 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1034718 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 948724 times.
✓ Branch 7 taken 85994 times.
1034718 for (const Create_field &new_field_def : alter_info->create_list) {
12871
4/4
✓ Branch 0 taken 918006 times.
✓ Branch 1 taken 30718 times.
✓ Branch 2 taken 663 times.
✓ Branch 3 taken 948061 times.
1866730 if (new_field_def.field != nullptr &&
12872
3/4
✓ Branch 0 taken 918006 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 663 times.
✓ Branch 3 taken 917343 times.
918006 new_field_def.field->type() == MYSQL_TYPE_GEOMETRY) {
12873 const Field_geom *field_geom =
12874 663 down_cast<const Field_geom *>(new_field_def.field);
12875
12876
6/6
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 615 times.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 40 times.
✓ Branch 5 taken 623 times.
711 if (field_geom->get_srid() != new_field_def.m_srid &&
12877 48 new_field_def.m_srid.has_value())
12878 40 return true;
12879 }
12880 }
12881 85994 return false;
12882 88231 }
12883
12884 /**
12885 Add MDL requests for exclusive lock on tables referenced by the
12886 foreign keys to be dropped by ALTER TABLE operation. Also add
12887 the referenced table names to the foreign key invalidator,
12888 to be used at a later stage to invalidate the dd::Table objects.
12889
12890 @param thd Thread handle.
12891 @param alter_info Alter_info object with the list of FKs
12892 to be dropped.
12893 @param table_def dd::Table describing the table before
12894 ALTER operation.
12895 @param hton Handlerton for table's storage engine.
12896 @param[in,out] mdl_requests List to which MDL requests are to be added.
12897 @param[in,out] fk_invalidator Object keeping track of which dd::Table
12898 objects to invalidate.
12899
12900 @retval operation outcome, false if no error.
12901 */
12902 75156 static bool collect_fk_parents_for_dropped_fks(
12903 THD *thd, const Alter_info *alter_info, const dd::Table *table_def,
12904 handlerton *hton, MDL_request_list *mdl_requests,
12905 Foreign_key_parents_invalidator *fk_invalidator) {
12906
2/2
✓ Branch 0 taken 9634 times.
✓ Branch 1 taken 75156 times.
84790 for (const Alter_drop *drop : alter_info->drop_list) {
12907
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 9571 times.
9634 if (drop->type == Alter_drop::FOREIGN_KEY) {
12908
6/10
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 63 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 63 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 63 times.
✓ Branch 9 taken 4 times.
67 for (const dd::Foreign_key *fk : table_def->foreign_keys()) {
12909
2/4
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
✗ Branch 3 not taken.
63 if (my_strcasecmp(system_charset_info, drop->name,
12910
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 4 times.
63 fk->name().c_str()) == 0) {
12911 char buff_db[NAME_LEN + 1];
12912 char buff_table[NAME_LEN + 1];
12913
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 my_stpncpy(buff_db, fk->referenced_table_schema_name().c_str(),
12914 NAME_LEN);
12915
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 my_stpncpy(buff_table, fk->referenced_table_name().c_str(), NAME_LEN);
12916
12917 /*
12918 In lower-case-table-names == 2 mode we store original versions
12919 of table and db names in the data-dictionary. Hence they need
12920 to be lowercased to produce correct MDL key for them and for
12921 other uses.
12922 */
12923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (lower_case_table_names == 2) {
12924 my_casedn_str(system_charset_info, buff_db);
12925 my_casedn_str(system_charset_info, buff_table);
12926 }
12927
12928
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 MDL_request *mdl_request = new (thd->mem_root) MDL_request;
12929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (mdl_request == nullptr) return true;
12930
12931
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 MDL_REQUEST_INIT(mdl_request, MDL_key::TABLE, buff_db, buff_table,
12932 MDL_EXCLUSIVE, MDL_STATEMENT);
12933
12934
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 mdl_requests->push_front(mdl_request);
12935
12936
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 mdl_request = new (thd->mem_root) MDL_request;
12937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (mdl_request == nullptr) return true;
12938
12939
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 MDL_REQUEST_INIT(mdl_request, MDL_key::SCHEMA, buff_db, "",
12940 MDL_INTENTION_EXCLUSIVE, MDL_STATEMENT);
12941
12942
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 mdl_requests->push_front(mdl_request);
12943
12944
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 fk_invalidator->add(buff_db, buff_table, hton);
12945 59 break;
12946 }
12947 }
12948 }
12949 }
12950 75156 return false;
12951 }
12952
12953 /**
12954 Acquire exclusive metadata locks on tables which definitions need to
12955 be updated or invalidated due to foreign keys created or dropped as
12956 result of complex ALTER TABLE operation.
12957 Also add the referenced table names for the FKs created/dropped to the
12958 foreign key invalidator, to be used at a later stage to invalidate the
12959 dd::Table objects.
12960
12961 @param thd Thread handle.
12962 @param table_list Table list element for table being ALTERed.
12963 @param old_table_def Old table definition of table being ALTERed.
12964 @param alter_ctx ALTER TABLE operation context.
12965 @param alter_info Alter_info object with the lists of FKs
12966 to be added or dropped.
12967 @param old_hton Table's old SE.
12968 @param new_hton Table's new SE.
12969 @param[in,out] fk_invalidator Object keeping track of which dd::Table
12970 objects to invalidate.
12971
12972 @retval operation outcome, false if no error.
12973 */
12974 75429 static bool collect_and_lock_fk_tables_for_complex_alter_table(
12975 THD *thd, TABLE_LIST *table_list, const dd::Table *old_table_def,
12976 const Alter_table_ctx *alter_ctx, const Alter_info *alter_info,
12977 handlerton *old_hton, handlerton *new_hton,
12978 Foreign_key_parents_invalidator *fk_invalidator) {
12979
1/2
✓ Branch 0 taken 75429 times.
✗ Branch 1 not taken.
75429 MDL_request_list mdl_requests;
12980
12981
2/4
✓ Branch 0 taken 75429 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 75429 times.
75429 if (collect_fk_parents_for_new_fks(
12982 thd, table_list->db, table_list->table_name, alter_info,
12983 MDL_EXCLUSIVE, new_hton, &mdl_requests, fk_invalidator))
12984 return true;
12985
12986
2/2
✓ Branch 0 taken 273 times.
✓ Branch 1 taken 75156 times.
75429 if (alter_ctx->is_table_renamed()) {
12987
2/4
✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 273 times.
273 if (collect_fk_parents_for_all_fks(thd, old_table_def, old_hton,
12988 MDL_EXCLUSIVE, &mdl_requests,
12989 fk_invalidator))
12990 return true;
12991 } else {
12992
2/4
✓ Branch 0 taken 75156 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 75156 times.
75156 if (collect_fk_parents_for_dropped_fks(thd, alter_info, old_table_def,
12993 old_hton, &mdl_requests,
12994 fk_invalidator))
12995 return true;
12996 }
12997
12998
2/2
✓ Branch 0 taken 803 times.
✓ Branch 1 taken 74626 times.
75429 if (new_hton != old_hton) {
12999 /*
13000 By changing table's storage engine we might be introducing parent
13001 table for previously orphan foreign keys in the new SE. We need
13002 to lock child tables of such orphan foreign keys. OTOH it is safe
13003 to assume that if SE is changed table can't be parent in any
13004 foreign keys in old SE.
13005 */
13006
2/4
✓ Branch 0 taken 803 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 803 times.
803 assert(old_table_def->foreign_key_parents().size() == 0);
13007
13008
2/4
✓ Branch 0 taken 803 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 803 times.
803 if (collect_fk_children(thd, table_list->db, table_list->table_name,
13009 new_hton, MDL_EXCLUSIVE, &mdl_requests))
13010 return true;
13011 } else {
13012
2/4
✓ Branch 0 taken 74626 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 74626 times.
74626 if (collect_fk_children(thd, old_table_def, MDL_EXCLUSIVE, &mdl_requests))
13013 return true;
13014 }
13015
13016
2/2
✓ Branch 0 taken 273 times.
✓ Branch 1 taken 75156 times.
75429 if (alter_ctx->is_table_renamed()) {
13017
2/4
✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 273 times.
273 if (collect_fk_children(thd, alter_ctx->new_db, alter_ctx->new_alias,
13018 new_hton, MDL_EXCLUSIVE, &mdl_requests))
13019 return true;
13020 }
13021
13022
4/4
✓ Branch 0 taken 313 times.
✓ Branch 1 taken 75116 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 75428 times.
75742 if (!mdl_requests.is_empty() &&
13023
3/4
✓ Branch 0 taken 313 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 312 times.
313 thd->mdl_context.acquire_locks(&mdl_requests,
13024 thd->variables.lock_wait_timeout))
13025 1 return true;
13026
13027 75428 return false;
13028 }
13029
13030 /**
13031 Update referenced table names and the unique constraint name for FKs
13032 affected by complex ALTER TABLE operation.
13033
13034 @param thd Thread handle.
13035 @param table_list Table list element for table being ALTERed.
13036 @param alter_ctx ALTER TABLE operation context.
13037 @param alter_info Alter_info describing ALTER TABLE, specifically
13038 containing information about columns being renamed.
13039 @param new_hton Table's new SE.
13040 @param fk_invalidator Object keeping track of which dd::Table
13041 objects to invalidate. Used to filter out
13042 which FK parents should have their FK parent
13043 information reloaded.
13044
13045 @retval operation outcome, false if no error.
13046 */
13047 63716 static bool adjust_fks_for_complex_alter_table(
13048 THD *thd, TABLE_LIST *table_list, Alter_table_ctx *alter_ctx,
13049 Alter_info *alter_info, handlerton *new_hton,
13050 const Foreign_key_parents_invalidator *fk_invalidator) {
13051
2/2
✓ Branch 0 taken 3461 times.
✓ Branch 1 taken 60255 times.
63716 if (!(new_hton->flags & HTON_SUPPORTS_FOREIGN_KEYS)) return false;
13052
13053 60255 const dd::Table *new_table = nullptr;
13054
4/8
✓ Branch 0 taken 60255 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 60255 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 60255 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 60255 times.
60255 if (thd->dd_client()->acquire(alter_ctx->new_db, alter_ctx->new_alias,
13055 &new_table))
13056 return true;
13057
13058
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60255 times.
60255 assert(new_table != nullptr);
13059
13060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60255 times.
60255 if (adjust_fk_children_after_parent_def_change(
13061 thd,
13062 /*
13063 For consistency with check_fk_children_after_parent_def_change(),
13064 allow charset discrepancies between child and parent columns in
13065 FOREIGN_KEY_CHECKS=0 mode.
13066 */
13067
1/2
✓ Branch 0 taken 60255 times.
✗ Branch 1 not taken.
60255 !(thd->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS),
13068 table_list->db, table_list->table_name, new_hton, new_table,
13069 alter_info, true))
13070 return true;
13071
13072
2/2
✓ Branch 0 taken 265 times.
✓ Branch 1 taken 59990 times.
60255 if (alter_ctx->is_table_renamed()) {
13073
2/4
✓ Branch 0 taken 265 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 265 times.
265 if (adjust_fk_children_after_parent_rename(
13074 thd, table_list->db, table_list->table_name, new_hton,
13075 alter_ctx->new_db, alter_ctx->new_alias))
13076 return true;
13077
13078
2/4
✓ Branch 0 taken 265 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 265 times.
265 if (adjust_fk_children_after_parent_def_change(
13079 thd, alter_ctx->new_db, alter_ctx->new_alias, new_hton, new_table,
13080 nullptr))
13081 return true;
13082 }
13083
13084
1/2
✓ Branch 0 taken 60255 times.
✗ Branch 1 not taken.
60255 return adjust_fk_parents(thd, alter_ctx->new_db, alter_ctx->new_alias, true,
13085 60255 fk_invalidator);
13086 }
13087
13088 /**
13089 Add appropriate MDL requests on names of foreign keys on the table
13090 to be renamed to the requests list.
13091
13092 @param thd Thread handle.
13093 @param db Table's old schema.
13094 @param table_name Table's old name.
13095 @param table_def Table definition of table being RENAMEd.
13096 @param hton Table's storage engine.
13097 @param new_db Table's new schema.
13098 @param new_table_name Table's new name.
13099 @param[in,out] mdl_requests List to which MDL requests need to be
13100 added.
13101
13102 @retval operation outcome, false if no error.
13103 */
13104
13105 2106 static bool collect_fk_names_for_rename_table(
13106 THD *thd, const char *db, const char *table_name,
13107 const dd::Table *table_def, handlerton *hton, const char *new_db,
13108 const char *new_table_name, MDL_request_list *mdl_requests)
13109
13110 {
13111 bool is_table_renamed =
13112
1/2
✓ Branch 0 taken 2106 times.
✗ Branch 1 not taken.
2106 (my_strcasecmp(table_alias_charset, table_name, new_table_name) != 0);
13113
1/2
✓ Branch 0 taken 2106 times.
✗ Branch 1 not taken.
2106 bool is_db_changed = (my_strcasecmp(table_alias_charset, db, new_db) != 0);
13114
13115 char old_table_name_norm[NAME_LEN + 1];
13116
1/2
✓ Branch 0 taken 2106 times.
✗ Branch 1 not taken.
2106 strmake(old_table_name_norm, table_name, NAME_LEN);
13117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2106 times.
2106 if (lower_case_table_names == 2)
13118 my_casedn_str(system_charset_info, old_table_name_norm);
13119 char new_table_name_lc[NAME_LEN + 1];
13120
1/2
✓ Branch 0 taken 2106 times.
✗ Branch 1 not taken.
2106 strmake(new_table_name_lc, new_table_name, NAME_LEN);
13121 /*
13122 Unless new table name in lower case already we need to lowercase
13123 it, so it can be used to construct lowercased version of FK name
13124 for acquiring metadata lock.
13125 */
13126
2/2
✓ Branch 0 taken 1980 times.
✓ Branch 1 taken 126 times.
2106 if (lower_case_table_names != 1)
13127
1/2
✓ Branch 0 taken 1980 times.
✗ Branch 1 not taken.
1980 my_casedn_str(system_charset_info, new_table_name_lc);
13128 2106 size_t old_table_name_norm_len = strlen(old_table_name_norm);
13129
13130
6/10
✓ Branch 0 taken 2106 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2106 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2106 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 28 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 28 times.
✓ Branch 9 taken 2106 times.
2134 for (const dd::Foreign_key *fk : table_def->foreign_keys()) {
13131 /*
13132 Since foreign key names are case-insensitive we need to lowercase
13133 them before passing to MDL subsystem.
13134 */
13135 char fk_name[NAME_LEN + 1];
13136
2/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
28 strmake(fk_name, fk->name().c_str(), NAME_LEN);
13137
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 my_casedn_str(system_charset_info, fk_name);
13138
13139
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 MDL_request *mdl_request = new (thd->mem_root) MDL_request;
13140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (mdl_request == nullptr) return true;
13141
13142
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 MDL_REQUEST_INIT(mdl_request, MDL_key::FOREIGN_KEY, db, fk_name,
13143 MDL_EXCLUSIVE, MDL_STATEMENT);
13144
13145
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 mdl_requests->push_front(mdl_request);
13146
13147
3/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 1 times.
56 if (is_table_renamed &&
13148
3/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 1 times.
28 dd::is_generated_foreign_key_name(old_table_name_norm,
13149 old_table_name_norm_len, hton, *fk)) {
13150 char new_fk_name[NAME_LEN + 1];
13151
13152 /*
13153 Copy <SE-specific or default FK name suffix><number> part.
13154 Here we truncate generated name if it is too long. This is sufficient
13155 for MDL purposes. Error will be reported later in this case.
13156 */
13157
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 strxnmov(new_fk_name, NAME_LEN, new_table_name_lc,
13158
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 fk->name().c_str() + old_table_name_norm_len, NullS);
13159
13160
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 MDL_request *mdl_request2 = new (thd->mem_root) MDL_request;
13161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (mdl_request2 == nullptr) return true;
13162
13163
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 MDL_REQUEST_INIT(mdl_request2, MDL_key::FOREIGN_KEY, new_db, new_fk_name,
13164 MDL_EXCLUSIVE, MDL_STATEMENT);
13165
13166
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 mdl_requests->push_front(mdl_request2);
13167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 } else if (is_db_changed) {
13168 MDL_request *mdl_request2 = new (thd->mem_root) MDL_request;
13169 if (mdl_request2 == nullptr) return true;
13170
13171 MDL_REQUEST_INIT(mdl_request2, MDL_key::FOREIGN_KEY, new_db, fk_name,
13172 MDL_EXCLUSIVE, MDL_STATEMENT);
13173
13174 mdl_requests->push_front(mdl_request2);
13175 }
13176 }
13177
13178 2106 return false;
13179 }
13180
13181 /**
13182 Check if complex ALTER TABLE with RENAME clause results in foreign key
13183 names conflicts.
13184
13185 @param thd Thread handle.
13186 @param table_list Table list element for table altered.
13187 @param table_def dd::Table object describing new version of
13188 table prior to rename operation.
13189 @param hton Table's storage engine.
13190 @param new_schema dd::Schema object for target schema.
13191 @param alter_ctx ALTER TABLE operation context.
13192
13193 @retval True if error (e.g. due to foreign key name conflict),
13194 false - otherwise.
13195 */
13196
13197 267 static bool check_fk_names_before_rename(THD *thd, TABLE_LIST *table_list,
13198 const dd::Table &table_def,
13199 handlerton *hton,
13200 const dd::Schema &new_schema,
13201 const Alter_table_ctx &alter_ctx) {
13202
6/10
✓ Branch 0 taken 267 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 267 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 267 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 267 times.
269 for (const dd::Foreign_key *fk : table_def.foreign_keys()) {
13203
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 if (alter_ctx.is_table_name_changed() &&
13204
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 dd::is_generated_foreign_key_name(
13205 table_list->table_name, table_list->table_name_length, hton, *fk)) {
13206 // We reserve extra NAME_LEN to ensure that new name fits.
13207 char new_fk_name[NAME_LEN + NAME_LEN + 1];
13208
13209 /*
13210 Construct new name by copying <FK name suffix><number> suffix
13211 from the old one.
13212 */
13213 2 strxnmov(new_fk_name, sizeof(new_fk_name) - 1, alter_ctx.new_name,
13214
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 fk->name().c_str() + table_list->table_name_length, NullS);
13215
13216
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (check_string_char_length(to_lex_cstring(new_fk_name), "",
13217 NAME_CHAR_LEN, system_charset_info,
13218 true /* no error */)) {
13219 my_error(ER_TOO_LONG_IDENT, MYF(0), new_fk_name);
13220 return true;
13221 }
13222
13223 bool exists;
13224
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 if (thd->dd_client()->check_foreign_key_exists(new_schema, new_fk_name,
13225 &exists))
13226 return true;
13227
13228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (exists) {
13229 my_error(ER_FK_DUP_NAME, MYF(0), new_fk_name);
13230 return true;
13231 }
13232 } else if (alter_ctx.is_database_changed()) {
13233 bool exists;
13234 if (thd->dd_client()->check_foreign_key_exists(new_schema, fk->name(),
13235 &exists))
13236 return true;
13237
13238 if (exists) {
13239 my_error(ER_FK_DUP_NAME, MYF(0), fk->name().c_str());
13240 return true;
13241 }
13242 }
13243 }
13244
13245 267 return false;
13246 }
13247
13248 /**
13249 Check if a table is empty, i.e., it has no rows.
13250
13251 @param[in] table The table.
13252 @param[out] is_empty Set to true if the table is empty.
13253
13254 @retval false Success.
13255 @retval true An error occurred (and has been reported with print_error).
13256 */
13257 109 static bool table_is_empty(TABLE *table, bool *is_empty) {
13258 109 *is_empty = false;
13259 109 int error = 0;
13260
1/2
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
109 if (!(error = table->file->ha_rnd_init(true))) {
13261 do {
13262 109 error = table->file->ha_rnd_next(table->record[0]);
13263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 109 times.
109 } while (error == HA_ERR_RECORD_DELETED);
13264
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 12 times.
109 if (error == HA_ERR_END_OF_FILE) *is_empty = true;
13265 }
13266
3/4
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 97 times.
109 if (error && error != HA_ERR_END_OF_FILE) {
13267 table->file->print_error(error, MYF(0));
13268 table->file->ha_rnd_end();
13269 return true;
13270 }
13271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 109 times.
109 if ((error = table->file->ha_rnd_end())) {
13272 table->file->print_error(error, MYF(0));
13273 return true;
13274 }
13275 109 return false;
13276 }
13277
13278 /**
13279 * Unloads table from secondary engine if SECONDARY_ENGINE = NULL.
13280 *
13281 * @param thd Thread handler.
13282 * @param table Table opened in primary storage engine.
13283 * @param create_info Information from the parsing phase about new
13284 * table properties.
13285 * @param old_table_def Definition of table before the alter statement.
13286 *
13287 * @return True if error, false otherwise.
13288 */
13289 79143 static bool remove_secondary_engine(THD *thd, const TABLE_LIST &table,
13290 const HA_CREATE_INFO &create_info,
13291 const dd::Table *old_table_def) {
13292 // Nothing to do if no secondary engine defined for the table.
13293
2/2
✓ Branch 0 taken 79115 times.
✓ Branch 1 taken 28 times.
79143 if (table.table->s->secondary_engine.str == nullptr) return false;
13294
13295 // Check if SECONDARY_ENGINE = NULL has been set in ALTER TABLE.
13296 28 const bool is_null =
13297
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
56 create_info.used_fields & HA_CREATE_USED_SECONDARY_ENGINE &&
13298
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 create_info.secondary_engine.str == nullptr;
13299
13300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (!is_null) return false;
13301
13302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (thd->mdl_context.upgrade_shared_lock(table.table->mdl_ticket,
13303 MDL_EXCLUSIVE,
13304 thd->variables.lock_wait_timeout))
13305 return true;
13306
13307 28 return secondary_engine_unload_table(thd, table.db, table.table_name,
13308 28 *old_table_def, false);
13309 }
13310
13311 /**
13312 Perform in-place alter table.
13313
13314 @param thd Thread handle.
13315 @param schema Source schema.
13316 @param new_schema Target schema.
13317 @param table_def Table object for the original table.
13318 @param altered_table_def Table object for the new version of the table.
13319 @param table_list TABLE_LIST for the table to change.
13320 @param table The original TABLE.
13321 @param altered_table TABLE object for new version of the table.
13322 @param ha_alter_info Structure describing ALTER TABLE to be carried
13323 out and serving as a storage place for data
13324 used during different phases.
13325 @param inplace_supported Enum describing the locking requirements.
13326 @param alter_ctx ALTER TABLE runtime context.
13327 @param columns A list of columns to be modified. This is needed
13328 for removal/renaming of histogram statistics.
13329 @param fk_key_info Array of FOREIGN_KEY objects describing foreign
13330 keys in new table version.
13331 @param fk_key_count Number of foreign keys in new table version.
13332 @param[out] fk_invalidator Set of parent tables which participate in FKs
13333 together with table being altered and which
13334 entries in DD cache need to be invalidated.
13335
13336 @retval true Error
13337 @retval false Success
13338
13339 @note
13340 If mysql_alter_table does not need to copy the table, it is
13341 either an alter table where the storage engine does not
13342 need to know about the change, only the frm will change,
13343 or the storage engine supports performing the alter table
13344 operation directly, in-place without mysql having to copy
13345 the table.
13346
13347 @note This function frees the TABLE object associated with the new version of
13348 the table and removes the .FRM file for it in case of both success and
13349 failure.
13350 */
13351
13352 57770 static bool mysql_inplace_alter_table(
13353 THD *thd, const dd::Schema &schema, const dd::Schema &new_schema,
13354 const dd::Table *table_def, dd::Table *altered_table_def,
13355 TABLE_LIST *table_list, TABLE *table, TABLE *altered_table,
13356 Alter_inplace_info *ha_alter_info,
13357 enum_alter_inplace_result inplace_supported, Alter_table_ctx *alter_ctx,
13358 histograms::columns_set &columns, FOREIGN_KEY *fk_key_info,
13359 uint fk_key_count, Foreign_key_parents_invalidator *fk_invalidator) {
13360
1/2
✓ Branch 0 taken 57770 times.
✗ Branch 1 not taken.
57770 handlerton *db_type = table->s->db_type();
13361 57770 MDL_ticket *mdl_ticket = table->mdl_ticket;
13362 57770 Alter_info *alter_info = ha_alter_info->alter_info;
13363 57770 bool reopen_tables = false;
13364 57770 bool rollback_needs_dict_cache_reset = false;
13365
1/2
✓ Branch 0 taken 57770 times.
✗ Branch 1 not taken.
57770 MDL_request_list mdl_requests;
13366
13367
1/2
✓ Branch 0 taken 57770 times.
✗ Branch 1 not taken.
57770 DBUG_TRACE;
13368
13369 /*
13370 Upgrade to EXCLUSIVE lock if:
13371 - This is requested by the storage engine
13372 - Or the storage engine needs exclusive lock for just the prepare
13373 phase
13374 - Or requested by the user
13375
13376 Note that we handle situation when storage engine needs exclusive
13377 lock for prepare phase under LOCK TABLES in the same way as when
13378 exclusive lock is required for duration of the whole statement.
13379 */
13380
4/4
✓ Branch 0 taken 57764 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 55820 times.
✓ Branch 3 taken 1944 times.
57770 if (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK ||
13381
2/2
✓ Branch 0 taken 45138 times.
✓ Branch 1 taken 10682 times.
55820 ((inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE ||
13382 47082 inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE) &&
13383
2/2
✓ Branch 0 taken 47012 times.
✓ Branch 1 taken 70 times.
47082 (thd->locked_tables_mode == LTM_LOCK_TABLES ||
13384
1/2
✓ Branch 0 taken 47012 times.
✗ Branch 1 not taken.
47012 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) ||
13385
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 57683 times.
57694 alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE) {
13386
2/4
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 87 times.
87 if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
13387 goto cleanup;
13388 /*
13389 Get rid of all TABLE instances belonging to this thread
13390 except one to be used for in-place ALTER TABLE.
13391
13392 This is mostly needed to satisfy InnoDB assumptions/asserts.
13393 */
13394
1/2
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
87 close_all_tables_for_name(thd, table->s, false, table);
13395 /*
13396 If we are under LOCK TABLES we will need to reopen tables which we
13397 just have closed in case of error.
13398 */
13399 87 reopen_tables = true;
13400
4/4
✓ Branch 0 taken 55748 times.
✓ Branch 1 taken 1935 times.
✓ Branch 2 taken 45067 times.
✓ Branch 3 taken 10681 times.
57683 } else if (inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE ||
13401 inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE) {
13402 /*
13403 Storage engine has requested exclusive lock only for prepare phase
13404 and we are not under LOCK TABLES.
13405 Don't mark TABLE_SHARE as old in this case, as this won't allow opening
13406 of table by other threads during main phase of in-place ALTER TABLE.
13407 */
13408
3/4
✓ Branch 0 taken 47002 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 46965 times.
47002 if (thd->mdl_context.upgrade_shared_lock(table->mdl_ticket, MDL_EXCLUSIVE,
13409 thd->variables.lock_wait_timeout))
13410 37 goto cleanup;
13411
13412 46965 tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE, table->s->db.str,
13413
1/2
✓ Branch 0 taken 46965 times.
✗ Branch 1 not taken.
46965 table->s->table_name.str, false);
13414 }
13415
13416 /*
13417 Upgrade to SHARED_NO_WRITE lock if:
13418 - The storage engine needs writes blocked for the whole duration
13419 - Or this is requested by the user
13420 Note that under LOCK TABLES, we will already have SHARED_NO_READ_WRITE.
13421 */
13422 115466 if ((inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK ||
13423
4/6
✓ Branch 0 taken 57733 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 57716 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 57733 times.
57750 alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED) &&
13424
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
17 thd->mdl_context.upgrade_shared_lock(table->mdl_ticket,
13425 MDL_SHARED_NO_WRITE,
13426 thd->variables.lock_wait_timeout)) {
13427 goto cleanup;
13428 }
13429
13430 /*
13431 Acquire locks on names of new foreign keys. INPLACE algorithm creates
13432 the new table definition in the original table's database.
13433 */
13434
2/4
✓ Branch 0 taken 57733 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57733 times.
✗ Branch 3 not taken.
57733 if (collect_fk_names_for_new_fks(
13435 thd, table_list->db, table_list->table_name, alter_info, db_type,
13436 get_fk_max_generated_name_number(table_list->table_name, table_def,
13437 db_type),
13438
4/6
✓ Branch 0 taken 57733 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 161 times.
✓ Branch 3 taken 57572 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 57733 times.
115627 &mdl_requests) ||
13439 57733 (alter_ctx->is_table_renamed() &&
13440
2/4
✓ Branch 0 taken 161 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 161 times.
161 collect_fk_names_for_rename_table(
13441 thd, table_list->db, table_list->table_name, altered_table_def,
13442 db_type, alter_ctx->new_db, alter_ctx->new_name, &mdl_requests)))
13443 goto cleanup;
13444
13445
3/4
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 57636 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 57733 times.
57830 if (!mdl_requests.is_empty() &&
13446
2/4
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 97 times.
97 thd->mdl_context.acquire_locks(&mdl_requests,
13447 thd->variables.lock_wait_timeout))
13448 goto cleanup;
13449
13450 /*
13451 Check if ALTER TABLE results in any foreign key name conflicts
13452 before starting potentially expensive phases of INPLACE ALTER.
13453 */
13454
4/10
✓ Branch 0 taken 57733 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57733 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 54173 times.
✓ Branch 5 taken 3560 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
115466 if (!dd::get_dictionary()->is_dd_table_name(table_list->db,
13455
6/10
✓ Branch 0 taken 57733 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57733 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 57733 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 57726 times.
✓ Branch 7 taken 7 times.
✓ Branch 8 taken 57733 times.
✗ Branch 9 not taken.
173192 table_list->table_name) &&
13456
2/2
✓ Branch 0 taken 54173 times.
✓ Branch 1 taken 3553 times.
57726 (db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS)) {
13457 54273 for (FOREIGN_KEY *fk = fk_key_info + alter_ctx->fk_count;
13458
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 54171 times.
54273 fk < fk_key_info + fk_key_count; ++fk) {
13459 bool exists;
13460
3/6
✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 102 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 102 times.
102 if (thd->dd_client()->check_foreign_key_exists(schema, fk->name, &exists))
13461 2 goto cleanup;
13462
13463
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 100 times.
102 if (exists) {
13464
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_FK_DUP_NAME, MYF(0), fk->name);
13465 2 goto cleanup;
13466 }
13467 }
13468
13469
3/4
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 54011 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 54171 times.
54331 if (alter_ctx->is_table_renamed() &&
13470
2/4
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 160 times.
160 check_fk_names_before_rename(thd, table_list, *altered_table_def,
13471 db_type, new_schema, *alter_ctx))
13472 goto cleanup;
13473 }
13474
13475 // It's now safe to take the table level lock.
13476
3/4
✓ Branch 0 taken 57731 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 57728 times.
57731 if (lock_tables(thd, table_list, alter_ctx->tables_opened, 0)) goto cleanup;
13477
13478
2/2
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 57619 times.
57728 if (alter_ctx->error_if_not_empty) {
13479 /*
13480 Storage engines should not suggest/support INSTANT algorithm if
13481 error_if_not_empty flag is set.
13482 The problem is that the below check if table is empty is not "instant",
13483 as it might have to traverse through deleted versions of rows on SQL-layer
13484 (e.g. MyISAM) or in SE (e.g. InnoDB).
13485
13486 OTOH for cases when table is empty difference between INSTANT and INPLACE
13487 or COPY algorithms should be negligible.
13488
13489 This limitation might be raised in the future if we will implement support
13490 for quick (i.e. non-traversing) check for table emptiness.
13491 */
13492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 109 times.
109 assert(inplace_supported != HA_ALTER_INPLACE_INSTANT);
13493 /*
13494 Operations which set error_if_not_empty flag typically request exclusive
13495 lock during prepare phase, so we don't have to upgrade lock to prevent
13496 concurrent table modifications here.
13497 */
13498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 109 times.
109 assert(table->mdl_ticket->get_type() == MDL_EXCLUSIVE);
13499 109 bool empty_table = false;
13500
2/4
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 109 times.
113 if (table_is_empty(table_list->table, &empty_table)) goto cleanup;
13501
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 97 times.
109 if (!empty_table) {
13502
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if (alter_ctx->error_if_not_empty &
13503 Alter_table_ctx::GEOMETRY_WITHOUT_DEFAULT) {
13504
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_INVALID_USE_OF_NULL, MYF(0));
13505
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 } else if ((alter_ctx->error_if_not_empty &
13506 10 Alter_table_ctx::DATETIME_WITHOUT_DEFAULT) &&
13507
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
10 (thd->variables.sql_mode & MODE_NO_ZERO_DATE)) {
13508 /*
13509 Report a warning if the NO ZERO DATE MODE is enabled. The
13510 warning will be promoted to an error if strict mode is
13511 also enabled. Do not check for errors here as we check
13512 thd->is_error() just below.
13513 */
13514
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 (void)push_zero_date_warning(thd, alter_ctx->datetime_field);
13515 }
13516
13517
3/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 8 times.
12 if (thd->is_error()) goto cleanup;
13518 }
13519
13520 // Empty table, so don't allow inserts during inplace operation.
13521
3/4
✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
✓ Branch 3 taken 6 times.
105 if (inplace_supported == HA_ALTER_INPLACE_NO_LOCK ||
13522 inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE)
13523 99 inplace_supported = HA_ALTER_INPLACE_SHARED_LOCK;
13524 }
13525
13526
3/4
✓ Branch 0 taken 55914 times.
✓ Branch 1 taken 1810 times.
✓ Branch 2 taken 55914 times.
✗ Branch 3 not taken.
57724 DEBUG_SYNC(thd, "alter_table_inplace_after_lock_upgrade");
13527
1/2
✓ Branch 0 taken 57724 times.
✗ Branch 1 not taken.
57724 THD_STAGE_INFO(thd, stage_alter_inplace_prepare);
13528
13529
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 45009 times.
✓ Branch 2 taken 12715 times.
✗ Branch 3 not taken.
57724 switch (inplace_supported) {
13530 case HA_ALTER_ERROR:
13531 case HA_ALTER_INPLACE_NOT_SUPPORTED:
13532 assert(0);
13533 [[fallthrough]];
13534 45009 case HA_ALTER_INPLACE_NO_LOCK:
13535 case HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE:
13536
2/3
✓ Branch 0 taken 44996 times.
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
45009 switch (alter_info->requested_lock) {
13537 44996 case Alter_info::ALTER_TABLE_LOCK_DEFAULT:
13538 case Alter_info::ALTER_TABLE_LOCK_NONE:
13539 44996 ha_alter_info->online = true;
13540 44996 break;
13541 13 case Alter_info::ALTER_TABLE_LOCK_SHARED:
13542 case Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE:
13543 13 break;
13544 }
13545 45009 break;
13546 12715 case HA_ALTER_INPLACE_EXCLUSIVE_LOCK:
13547 case HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE:
13548 case HA_ALTER_INPLACE_SHARED_LOCK:
13549 case HA_ALTER_INPLACE_INSTANT:
13550 12715 break;
13551 }
13552
13553 {
13554 /*
13555 We want warnings/errors about data truncation emitted when
13556 values of virtual columns are evaluated in INPLACE algorithm.
13557 */
13558 57724 thd->check_for_truncated_fields = CHECK_FIELD_WARN;
13559 57724 thd->num_truncated_fields = 0L;
13560
13561
3/4
✓ Branch 0 taken 57511 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 278 times.
✓ Branch 3 taken 57233 times.
57724 if (table->file->ha_prepare_inplace_alter_table(
13562 altered_table, ha_alter_info, table_def, altered_table_def)) {
13563 278 goto rollback;
13564 }
13565
13566 /*
13567 Downgrade the lock if storage engine has told us that exclusive lock was
13568 necessary only for prepare phase (unless we are not under LOCK TABLES) and
13569 user has not explicitly requested exclusive lock.
13570 */
13571
4/4
✓ Branch 0 taken 55404 times.
✓ Branch 1 taken 1829 times.
✓ Branch 2 taken 44617 times.
✓ Branch 3 taken 10787 times.
57233 if ((inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE ||
13572 46446 inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE) &&
13573
2/2
✓ Branch 0 taken 46377 times.
✓ Branch 1 taken 69 times.
46446 !(thd->locked_tables_mode == LTM_LOCK_TABLES ||
13574
1/2
✓ Branch 0 taken 46377 times.
✗ Branch 1 not taken.
46377 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) &&
13575
2/2
✓ Branch 0 taken 46367 times.
✓ Branch 1 taken 10 times.
46377 (alter_info->requested_lock !=
13576 Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE)) {
13577 /* If storage engine or user requested shared lock downgrade to SNW. */
13578
2/2
✓ Branch 0 taken 44546 times.
✓ Branch 1 taken 1821 times.
46367 if (inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE ||
13579
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 44539 times.
44546 alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED)
13580
1/2
✓ Branch 0 taken 1828 times.
✗ Branch 1 not taken.
1828 table->mdl_ticket->downgrade_lock(MDL_SHARED_NO_WRITE);
13581 else {
13582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44539 times.
44539 assert(inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE);
13583
1/2
✓ Branch 0 taken 44539 times.
✗ Branch 1 not taken.
44539 table->mdl_ticket->downgrade_lock(MDL_SHARED_UPGRADABLE);
13584 }
13585 }
13586
13587
3/4
✓ Branch 0 taken 55423 times.
✓ Branch 1 taken 1810 times.
✓ Branch 2 taken 55422 times.
✗ Branch 3 not taken.
57233 DEBUG_SYNC(thd, "alter_table_inplace_after_lock_downgrade");
13588
1/2
✓ Branch 0 taken 57232 times.
✗ Branch 1 not taken.
57232 THD_STAGE_INFO(thd, stage_alter_inplace);
13589
13590
3/4
✓ Branch 0 taken 57229 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 163 times.
✓ Branch 3 taken 57066 times.
57232 if (table->file->ha_inplace_alter_table(altered_table, ha_alter_info,
13591 table_def, altered_table_def)) {
13592 163 goto rollback;
13593 }
13594
13595 // Upgrade to EXCLUSIVE before commit.
13596
3/4
✓ Branch 0 taken 57066 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 57056 times.
57066 if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
13597 10 goto rollback;
13598
13599
3/4
✓ Branch 0 taken 57056 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 57055 times.
57056 if (collect_and_lock_fk_tables_for_complex_alter_table(
13600 thd, table_list, table_def, alter_ctx, alter_info, db_type, db_type,
13601 fk_invalidator))
13602 1 goto rollback;
13603
13604 /*
13605 Check if this is an ALTER command that will cause histogram statistics to
13606 become invalid. If that is the case; remove the histogram statistics.
13607
13608 This will take care of scenarios when INPLACE alter is used, but not COPY.
13609 */
13610
3/4
✓ Branch 0 taken 57055 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 57054 times.
57055 if (alter_table_drop_histograms(thd, table_list, ha_alter_info->alter_info,
13611 ha_alter_info->create_info, columns,
13612 table_def, altered_table_def))
13613 1 goto rollback;
13614
13615 /*
13616 If we are killed after this point, we should ignore and continue.
13617 We have mostly completed the operation at this point, there should
13618 be no long waits left.
13619 */
13620
13621
5/8
✓ Branch 0 taken 57054 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 57049 times.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
57054 DBUG_EXECUTE_IF("alter_table_rollback_new_index", {
13622 table->file->ha_commit_inplace_alter_table(
13623 altered_table, ha_alter_info, false, table_def, altered_table_def);
13624 my_error(ER_UNKNOWN_ERROR, MYF(0));
13625 thd->check_for_truncated_fields = CHECK_FIELD_IGNORE;
13626 goto cleanup;
13627 });
13628
13629
3/4
✓ Branch 0 taken 55239 times.
✓ Branch 1 taken 1810 times.
✓ Branch 2 taken 55239 times.
✗ Branch 3 not taken.
57049 DEBUG_SYNC(thd, "alter_table_inplace_before_commit");
13630
1/2
✓ Branch 0 taken 57049 times.
✗ Branch 1 not taken.
57049 THD_STAGE_INFO(thd, stage_alter_inplace_commit);
13631
13632
3/4
✓ Branch 0 taken 56897 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 56838 times.
57049 if (table->file->ha_commit_inplace_alter_table(
13633 altered_table, ha_alter_info, true, table_def, altered_table_def)) {
13634 59 goto rollback;
13635 }
13636
13637 56838 thd->check_for_truncated_fields = CHECK_FIELD_IGNORE;
13638
13639
1/2
✓ Branch 0 taken 56838 times.
✗ Branch 1 not taken.
56838 close_all_tables_for_name(thd, table->s, false, nullptr);
13640 56838 table_list->table = table = nullptr;
13641 56838 reopen_tables = true;
13642
1/2
✓ Branch 0 taken 56838 times.
✗ Branch 1 not taken.
56838 close_temporary_table(thd, altered_table, true, false);
13643 56838 rollback_needs_dict_cache_reset = true;
13644
13645 /*
13646 Replace table definition in the data-dictionary.
13647
13648 Note that any error after this point is really awkward for storage engines
13649 which don't support atomic DDL. Changes to table in SE are already
13650 committed and can't be rolled back. Failure to update data-dictionary or
13651 binary log will create inconsistency between them and SE. Since we can't
13652 do much in this situation we simply return error and hope that old table
13653 definition is compatible enough with a new one.
13654
13655 For engines supporting atomic DDL error is business-as-usual situation.
13656 Rollback of statement which happens on error should revert changes to
13657 table in SE as well.
13658 */
13659
2/4
✓ Branch 0 taken 56838 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56838 times.
✗ Branch 3 not taken.
56838 altered_table_def->set_schema_id(table_def->schema_id());
13660
2/4
✓ Branch 0 taken 56838 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56838 times.
✗ Branch 3 not taken.
56838 altered_table_def->set_name(alter_ctx->alias);
13661
1/2
✓ Branch 0 taken 56838 times.
✗ Branch 1 not taken.
56838 altered_table_def->set_hidden(dd::Abstract_table::HT_VISIBLE);
13662
13663 /*
13664 Copy pre-existing triggers to the new table definition.
13665 Since trigger names have to be unique per schema, we cannot
13666 create them while both the old and the new version of the
13667 table definition exist. Note that we drop the old table before
13668 we call update on the new table definition.
13669 */
13670
1/2
✓ Branch 0 taken 56838 times.
✗ Branch 1 not taken.
56838 altered_table_def->copy_triggers(table_def);
13671
13672 /* About the remove the old table definition, if there any columns
13673 with compression dictionary, remove the entries from
13674 mysql.compression_dictionary_cols table */
13675
2/4
✓ Branch 0 taken 56838 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 56838 times.
56838 if (compression_dict::cols_table_delete(thd, *table_def)) {
13676 goto cleanup2;
13677 }
13678
13679
2/4
✓ Branch 0 taken 56838 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 56838 times.
56838 if (thd->dd_client()->drop(table_def)) goto cleanup2;
13680 56838 table_def = nullptr;
13681
13682
3/4
✓ Branch 0 taken 55028 times.
✓ Branch 1 taken 1810 times.
✓ Branch 2 taken 55028 times.
✗ Branch 3 not taken.
56838 DEBUG_SYNC_C("alter_table_after_dd_client_drop");
13683
13684 // Reset check constraint's mode.
13685
1/2
✓ Branch 0 taken 56838 times.
✗ Branch 1 not taken.
56838 reset_check_constraints_alter_mode(altered_table_def);
13686
13687
2/2
✓ Branch 0 taken 53377 times.
✓ Branch 1 taken 3461 times.
56838 if ((db_type->flags & HTON_SUPPORTS_ATOMIC_DDL)) {
13688 /*
13689 For engines supporting atomic DDL we have delayed storing new
13690 table definition in the data-dictionary so far in order to avoid
13691 conflicts between old and new definitions on foreign key names.
13692 Since the old table definition is gone we can safely store new
13693 definition now.
13694 */
13695
3/4
✓ Branch 0 taken 53377 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 53375 times.
53377 if (thd->dd_client()->store(altered_table_def)) goto cleanup2;
13696 } else {
13697
2/4
✓ Branch 0 taken 3461 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3461 times.
3461 if (thd->dd_client()->update(altered_table_def)) goto cleanup2;
13698
13699 /*
13700 Persist changes to data-dictionary for storage engines which don't
13701 support atomic DDL. Such SEs can't rollback in-place changes if error
13702 or crash happens after this point, so we are better to have
13703 data-dictionary in sync with SE.
13704
13705 Prevent intermediate commits to invoke commit order
13706 */
13707
1/2
✓ Branch 0 taken 3461 times.
✗ Branch 1 not taken.
3461 Implicit_substatement_state_guard substatement_guard(thd);
13708
13709
5/10
✓ Branch 0 taken 3461 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3461 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3461 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3461 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3461 times.
3461 if (trans_commit_stmt(thd) || trans_commit_implicit(thd)) goto cleanup2;
13710
1/2
✓ Branch 0 taken 3461 times.
✗ Branch 1 not taken.
3461 }
13711 }
13712
13713 #ifdef HAVE_PSI_TABLE_INTERFACE
13714 PSI_TABLE_CALL(drop_table_share)
13715 56836 (true, alter_ctx->new_db, static_cast<int>(strlen(alter_ctx->new_db)),
13716
1/2
✓ Branch 0 taken 56836 times.
✗ Branch 1 not taken.
56836 alter_ctx->tmp_name, static_cast<int>(strlen(alter_ctx->tmp_name)));
13717 #endif
13718
13719
2/8
✓ Branch 0 taken 56836 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 56836 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
56836 DBUG_EXECUTE_IF("crash_after_index_create",
13720 DBUG_SET("-d,crash_after_index_create");
13721 DBUG_SUICIDE(););
13722
13723 /*
13724 Tell the SE that the changed table in the data-dictionary.
13725 For engines which don't support atomic DDL this needs to be
13726 done before trying to rename the table.
13727 */
13728
2/2
✓ Branch 0 taken 3461 times.
✓ Branch 1 taken 53375 times.
56836 if (!(db_type->flags & HTON_SUPPORTS_ATOMIC_DDL)) {
13729
1/2
✓ Branch 0 taken 3461 times.
✗ Branch 1 not taken.
3461 Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN);
13730
13731 3461 table_list->mdl_request.ticket = mdl_ticket;
13732
2/4
✓ Branch 0 taken 3461 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3461 times.
3461 if (open_table(thd, table_list, &ot_ctx)) goto cleanup2;
13733
13734
1/2
✓ Branch 0 taken 3461 times.
✗ Branch 1 not taken.
3461 table_list->table->file->ha_notify_table_changed(ha_alter_info);
13735
13736 /*
13737 We might be going to reopen table down on the road, so we have to
13738 restore state of the TABLE object which we used for obtaining of
13739 handler object to make it usable for later reopening.
13740 */
13741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3461 times.
3461 assert(table_list->table == thd->open_tables);
13742
1/2
✓ Branch 0 taken 3461 times.
✗ Branch 1 not taken.
3461 close_thread_table(thd, &thd->open_tables);
13743 3461 table_list->table = nullptr;
13744
13745 /*
13746 Remove TABLE and TABLE_SHARE for from the TDC as we might have to
13747 rename table later.
13748 */
13749
1/2
✓ Branch 0 taken 3461 times.
✗ Branch 1 not taken.
3461 tdc_remove_table(thd, TDC_RT_REMOVE_ALL, alter_ctx->db,
13750 alter_ctx->table_name, false);
13751 }
13752
13753 // Rename altered table if requested.
13754
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 56676 times.
56836 if (alter_ctx->is_table_renamed()) {
13755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
160 if (mysql_rename_table(
13756 thd, db_type, alter_ctx->db, alter_ctx->table_name, alter_ctx->db,
13757 alter_ctx->table_name, new_schema, alter_ctx->new_db,
13758 alter_ctx->new_alias,
13759
1/2
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
160 ((db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) ? NO_DD_COMMIT : 0))) {
13760 /*
13761 If the rename fails we will still have a working table
13762 with the old name, but with other changes applied.
13763 */
13764 goto cleanup2;
13765 }
13766 }
13767
13768 /*
13769 We don't have SEs which support FKs and don't support atomic DDL.
13770 If we ever to support such engines we need to decide how to handle
13771 errors in the below code for them.
13772 */
13773
3/4
✓ Branch 0 taken 53375 times.
✓ Branch 1 taken 3461 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 53375 times.
56836 assert(!(db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS) ||
13774 (db_type->flags & HTON_SUPPORTS_ATOMIC_DDL));
13775
13776
2/4
✓ Branch 0 taken 56836 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 56836 times.
56836 if (adjust_fks_for_complex_alter_table(thd, table_list, alter_ctx, alter_info,
13777 db_type, fk_invalidator))
13778 goto cleanup2;
13779
13780
1/2
✓ Branch 0 taken 56836 times.
✗ Branch 1 not taken.
56836 THD_STAGE_INFO(thd, stage_end);
13781
13782
2/6
✓ Branch 0 taken 56836 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 56836 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
56836 DBUG_EXECUTE_IF("sleep_alter_before_main_binlog", my_sleep(6000000););
13783
3/4
✓ Branch 0 taken 55026 times.
✓ Branch 1 taken 1810 times.
✓ Branch 2 taken 55026 times.
✗ Branch 3 not taken.
56836 DEBUG_SYNC(thd, "alter_table_before_main_binlog");
13784
13785 113672 ha_binlog_log_query(thd, ha_alter_info->create_info->db_type,
13786
3/6
✓ Branch 0 taken 56836 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56836 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 56836 times.
✗ Branch 5 not taken.
56836 LOGCOM_ALTER_TABLE, thd->query().str, thd->query().length,
13787 alter_ctx->db, alter_ctx->table_name);
13788
13789
5/6
✓ Branch 0 taken 26882 times.
✓ Branch 1 taken 29954 times.
✓ Branch 2 taken 25111 times.
✓ Branch 3 taken 1771 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 25111 times.
56836 assert(!(mysql_bin_log.is_open() &&
13790 thd->is_current_stmt_binlog_format_row() &&
13791 (ha_alter_info->create_info->options & HA_LEX_CREATE_TMP_TABLE)));
13792
13793
4/6
✓ Branch 0 taken 56836 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56836 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 56832 times.
56836 if (write_bin_log(thd, true, thd->query().str, thd->query().length,
13794
1/2
✓ Branch 0 taken 56836 times.
✗ Branch 1 not taken.
56836 (db_type->flags & HTON_SUPPORTS_ATOMIC_DDL)))
13795 4 goto cleanup2;
13796
13797 {
13798
1/2
✓ Branch 0 taken 56832 times.
✗ Branch 1 not taken.
56832 Uncommitted_tables_guard uncommitted_tables(thd);
13799
13800
1/2
✓ Branch 0 taken 56832 times.
✗ Branch 1 not taken.
56832 uncommitted_tables.add_table(table_list);
13801
13802 bool views_err =
13803 56832 (alter_ctx->is_table_renamed()
13804
2/2
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 56674 times.
56990 ? update_referencing_views_metadata(
13805 thd, table_list, alter_ctx->new_db, alter_ctx->new_name,
13806
1/2
✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
158 !(db_type->flags & HTON_SUPPORTS_ATOMIC_DDL),
13807 &uncommitted_tables)
13808 56674 : update_referencing_views_metadata(
13809 thd, table_list,
13810
1/2
✓ Branch 0 taken 56674 times.
✗ Branch 1 not taken.
56674 !(db_type->flags & HTON_SUPPORTS_ATOMIC_DDL),
13811 56832 &uncommitted_tables));
13812
13813
2/2
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 56674 times.
56832 if (alter_ctx->is_table_renamed())
13814
1/2
✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
158 tdc_remove_table(thd, TDC_RT_REMOVE_ALL, alter_ctx->new_db,
13815 alter_ctx->new_name, false);
13816
13817
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 56831 times.
56832 if (views_err) goto cleanup2;
13818
2/2
✓ Branch 0 taken 56831 times.
✓ Branch 1 taken 1 times.
56832 }
13819
13820
3/4
✓ Branch 0 taken 55021 times.
✓ Branch 1 taken 1810 times.
✓ Branch 2 taken 55021 times.
✗ Branch 3 not taken.
56831 DEBUG_SYNC(thd, "action_after_write_bin_log");
13821
13822
2/2
✓ Branch 0 taken 53371 times.
✓ Branch 1 taken 3460 times.
56831 if (db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) {
13823 53371 enum_implicit_substatement_guard_mode mode =
13824 enum_implicit_substatement_guard_mode ::
13825 ENABLE_GTID_AND_SPCO_IF_SPCO_ACTIVE;
13826
13827 /* Disable GTID and SPCO for OPTIMIZE TABLE to avoid deadlock. */
13828
2/2
✓ Branch 0 taken 2065 times.
✓ Branch 1 taken 51306 times.
53371 if (thd->lex->sql_command == SQLCOM_OPTIMIZE)
13829 2065 mode = enum_implicit_substatement_guard_mode ::
13830 DISABLE_GTID_AND_SPCO_IF_SPCO_ACTIVE;
13831
13832 /*
13833 It allows saving GTID and invoking commit order, except when
13834 replica-preserve-commit-order is enabled and OPTIMIZE TABLE command
13835 is getting executed. The exception for OPTIMIZE TABLE command is
13836 because if it does enter commit order here and at the same time
13837 any operation on the table which is getting optimized is done,
13838 it results in deadlock.
13839 */
13840
1/2
✓ Branch 0 taken 53371 times.
✗ Branch 1 not taken.
53371 Implicit_substatement_state_guard guard(thd, mode);
13841
13842 /*
13843 Commit ALTER TABLE. Needs to be done here and not in the callers
13844 (which do it anyway) to be able notify SE about changed table.
13845 */
13846
5/10
✓ Branch 0 taken 53371 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53371 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 53338 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 53338 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 53338 times.
53371 if (trans_commit_stmt(thd) || trans_commit_implicit(thd)) goto cleanup2;
13847
13848 /* Call SE DDL post-commit hook. */
13849
2/4
✓ Branch 0 taken 53338 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53253 times.
✗ Branch 3 not taken.
53338 if (db_type->post_ddl) db_type->post_ddl(thd);
13850
13851 /*
13852 Finally we can tell SE supporting atomic DDL that the changed table
13853 in the data-dictionary.
13854 */
13855 TABLE_LIST new_table_list(alter_ctx->new_db, alter_ctx->new_name,
13856
1/2
✓ Branch 0 taken 53253 times.
✗ Branch 1 not taken.
53253 alter_ctx->new_alias, TL_READ);
13857 53253 new_table_list.mdl_request.ticket =
13858
2/2
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 53095 times.
53253 alter_ctx->is_table_renamed() ? alter_ctx->target_mdl_request.ticket
13859 : mdl_ticket;
13860
13861
1/2
✓ Branch 0 taken 53253 times.
✗ Branch 1 not taken.
53253 Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN);
13862
13863
3/4
✓ Branch 0 taken 53253 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 53252 times.
53253 if (open_table(thd, &new_table_list, &ot_ctx)) return true;
13864
13865
1/2
✓ Branch 0 taken 53252 times.
✗ Branch 1 not taken.
53252 new_table_list.table->file->ha_notify_table_changed(ha_alter_info);
13866
13867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53252 times.
53252 assert(new_table_list.table == thd->open_tables);
13868
1/2
✓ Branch 0 taken 53252 times.
✗ Branch 1 not taken.
53252 close_thread_table(thd, &thd->open_tables);
13869
2/3
✓ Branch 0 taken 53252 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
53253 }
13870
13871 // TODO: May move the opening of the table and the call to
13872 // ha_notify_table_changed() here to make sure we don't
13873 // notify the handler until all meta data is complete.
13874
13875 56712 return false;
13876
13877 512 rollback:
13878
1/2
✓ Branch 0 taken 512 times.
✗ Branch 1 not taken.
512 table->file->ha_commit_inplace_alter_table(
13879 altered_table, ha_alter_info, false, table_def, altered_table_def);
13880 512 thd->check_for_truncated_fields = CHECK_FIELD_IGNORE;
13881
13882 563 cleanup:
13883
1/2
✓ Branch 0 taken 563 times.
✗ Branch 1 not taken.
563 close_temporary_table(thd, altered_table, true, false);
13884
13885 570 cleanup2:
13886
13887
1/2
✓ Branch 0 taken 570 times.
✗ Branch 1 not taken.
570 (void)trans_rollback_stmt(thd);
13888 /*
13889 Full rollback in case we have THD::transaction_rollback_request
13890 and to synchronize DD state in cache and on disk (as statement
13891 rollback doesn't clear DD cache of modified uncommitted objects).
13892 */
13893
1/2
✓ Branch 0 taken 570 times.
✗ Branch 1 not taken.
570 (void)trans_rollback(thd);
13894
13895
3/4
✓ Branch 0 taken 483 times.
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 483 times.
✗ Branch 3 not taken.
570 if ((db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) && db_type->post_ddl)
13896
1/2
✓ Branch 0 taken 483 times.
✗ Branch 1 not taken.
483 db_type->post_ddl(thd);
13897
13898 /*
13899 InnoDB requires additional SE dictionary cache invalidation if we roll back
13900 after successful call to handler::ha_commit_inplace_alter_table().
13901 */
13902
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 563 times.
570 if (rollback_needs_dict_cache_reset) {
13903
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 if (db_type->dict_cache_reset != nullptr)
13904
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 db_type->dict_cache_reset(alter_ctx->db, alter_ctx->table_name);
13905 }
13906
13907 /*
13908 Re-opening of table needs to be done after rolling back the failed
13909 statement/transaction and clearing THD::transaction_rollback_request
13910 flag.
13911 */
13912
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 538 times.
570 if (reopen_tables) {
13913 /* Close the only table instance which might be still around. */
13914
3/4
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
32 if (table) close_all_tables_for_name(thd, table->s, false, nullptr);
13915
13916 /*
13917 For engines which support atomic DDL all changes were reverted
13918 by this point, so we can safely reopen them using old name.
13919
13920 For engines which do not support atomic DDL we can't be sure
13921 that rename step was reverted, so we simply remove table from
13922 the list of locked tables. We also downgrade/release metadata
13923 locks later. This won't mess up FK-related invariants for LOCK
13924 TABLES as such engines do not support FKs.
13925 */
13926
6/6
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 24 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 31 times.
57 if (!(db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) &&
13927 25 alter_ctx->is_table_renamed()) {
13928
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(!(db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS));
13929
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 thd->locked_tables_list.unlink_all_closed_tables(thd, nullptr, 0);
13930 }
13931
13932
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 (void)thd->locked_tables_list.reopen_tables(thd);
13933 }
13934
13935
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 483 times.
570 if (!(db_type->flags & HTON_SUPPORTS_ATOMIC_DDL)) {
13936 87 const dd::Table *drop_table_def = nullptr;
13937
4/10
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 86 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
174 if (!thd->dd_client()->acquire(alter_ctx->new_db, alter_ctx->tmp_name,
13938
4/8
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 87 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 87 times.
✗ Branch 7 not taken.
261 &drop_table_def) &&
13939
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 1 times.
87 (drop_table_def != nullptr)) {
13940
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 bool result = dd::drop_table(thd, alter_ctx->new_db, alter_ctx->tmp_name,
13941 *drop_table_def);
13942
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 (void)trans_intermediate_ddl_commit(thd, result);
13943 }
13944 }
13945
13946
2/2
✓ Branch 0 taken 543 times.
✓ Branch 1 taken 27 times.
570 if (thd->locked_tables_mode == LTM_LOCK_TABLES ||
13947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 543 times.
543 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)
13948
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
13949
13950 570 return true;
13951 57283 }
13952
13953 /**
13954 maximum possible length for certain blob types.
13955
13956 @param[in] type Blob type (e.g. MYSQL_TYPE_TINY_BLOB)
13957
13958 @return
13959 length
13960 */
13961
13962 15038 static uint blob_length_by_type(enum_field_types type) {
13963
4/5
✓ Branch 0 taken 2575 times.
✓ Branch 1 taken 11928 times.
✓ Branch 2 taken 200 times.
✓ Branch 3 taken 335 times.
✗ Branch 4 not taken.
15038 switch (type) {
13964 2575 case MYSQL_TYPE_TINY_BLOB:
13965 2575 return 255;
13966 11928 case MYSQL_TYPE_BLOB:
13967 11928 return 65535;
13968 200 case MYSQL_TYPE_MEDIUM_BLOB:
13969 200 return 16777215;
13970 335 case MYSQL_TYPE_LONG_BLOB:
13971 335 return 4294967295U;
13972 default:
13973 assert(0); // we should never go here
13974 return 0;
13975 }
13976 }
13977
13978 /**
13979 Convert the old temporal data types to the new temporal
13980 type format for ADD/CHANGE COLUMN, ADD INDEXES and ALTER
13981 FORCE ALTER operation.
13982
13983 @param thd Thread context.
13984 @param alter_info Alter info parameters.
13985
13986 @retval true Error.
13987 @retval false Either the old temporal data types
13988 are not present or they are present
13989 and have been successfully upgraded.
13990 */
13991
13992 88227 static bool upgrade_old_temporal_types(THD *thd, Alter_info *alter_info) {
13993 88227 bool old_temporal_type_present = false;
13994
13995
1/2
✓ Branch 0 taken 88227 times.
✗ Branch 1 not taken.
88227 DBUG_TRACE;
13996
13997
2/2
✓ Branch 0 taken 69318 times.
✓ Branch 1 taken 18909 times.
88227 if (!((alter_info->flags & Alter_info::ALTER_ADD_COLUMN) ||
13998
2/2
✓ Branch 0 taken 54665 times.
✓ Branch 1 taken 14653 times.
69318 (alter_info->flags & Alter_info::ALTER_ADD_INDEX) ||
13999
2/2
✓ Branch 0 taken 37547 times.
✓ Branch 1 taken 17118 times.
54665 (alter_info->flags & Alter_info::ALTER_CHANGE_COLUMN) ||
14000
2/2
✓ Branch 0 taken 37453 times.
✓ Branch 1 taken 94 times.
37547 (alter_info->flags & Alter_info::ALTER_RECREATE)))
14001 37453 return false;
14002
14003 /*
14004 Upgrade the old temporal types if any, for ADD/CHANGE COLUMN/
14005 ADD INDEXES and FORCE ALTER operation.
14006 */
14007 Create_field *def;
14008
1/2
✓ Branch 0 taken 50774 times.
✗ Branch 1 not taken.
50774 List_iterator<Create_field> create_it(alter_info->create_list);
14009
14010
2/2
✓ Branch 0 taken 748321 times.
✓ Branch 1 taken 50774 times.
799095 while ((def = create_it++)) {
14011 // Check if any old temporal type is present.
14012
1/2
✓ Branch 0 taken 748321 times.
✗ Branch 1 not taken.
748321 if ((def->sql_type == MYSQL_TYPE_TIME) ||
14013
1/2
✓ Branch 0 taken 748321 times.
✗ Branch 1 not taken.
748321 (def->sql_type == MYSQL_TYPE_DATETIME) ||
14014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 748321 times.
748321 (def->sql_type == MYSQL_TYPE_TIMESTAMP)) {
14015 old_temporal_type_present = true;
14016 break;
14017 }
14018 }
14019
14020 // Upgrade is not required since there are no old temporal types.
14021
1/2
✓ Branch 0 taken 50774 times.
✗ Branch 1 not taken.
50774 if (!old_temporal_type_present) return false;
14022
14023 // Upgrade old temporal types to the new temporal types.
14024 create_it.rewind();
14025 while ((def = create_it++)) {
14026 enum enum_field_types sql_type;
14027 Item *default_value = def->constant_default;
14028 Item *update_value = nullptr;
14029
14030 /*
14031 Set CURRENT_TIMESTAMP as default/update value based on
14032 the auto_flags value.
14033 */
14034
14035 if ((def->sql_type == MYSQL_TYPE_DATETIME ||
14036 def->sql_type == MYSQL_TYPE_TIMESTAMP) &&
14037 (def->auto_flags != Field::NONE)) {
14038 Item_func_now_local *now = new (thd->mem_root) Item_func_now_local(0);
14039 if (!now) return true;
14040
14041 if (def->auto_flags & Field::DEFAULT_NOW) default_value = now;
14042 if (def->auto_flags & Field::ON_UPDATE_NOW) update_value = now;
14043 }
14044
14045 switch (def->sql_type) {
14046 case MYSQL_TYPE_TIME:
14047 sql_type = MYSQL_TYPE_TIME2;
14048 break;
14049 case MYSQL_TYPE_DATETIME:
14050 sql_type = MYSQL_TYPE_DATETIME2;
14051 break;
14052 case MYSQL_TYPE_TIMESTAMP:
14053 sql_type = MYSQL_TYPE_TIMESTAMP2;
14054 break;
14055 default:
14056 continue;
14057 }
14058
14059 // Replace the old temporal field with the new temporal field.
14060 Create_field *temporal_field = nullptr;
14061 if (!(temporal_field = new (thd->mem_root) Create_field()) ||
14062 temporal_field->init(thd, def->field_name, sql_type, nullptr, nullptr,
14063 (def->flags & NOT_NULL_FLAG), default_value,
14064 update_value, &def->comment, def->change, nullptr,
14065 nullptr, false, 0, &def->zip_dict_name, nullptr,
14066 nullptr, def->m_srid, def->hidden, def->is_array))
14067 return true;
14068
14069 temporal_field->field = def->field;
14070 create_it.replace(temporal_field);
14071 }
14072
14073 // Report a NOTE informing about the upgrade.
14074 push_warning(thd, Sql_condition::SL_NOTE, ER_OLD_TEMPORALS_UPGRADED,
14075 ER_THD(thd, ER_OLD_TEMPORALS_UPGRADED));
14076 return false;
14077 88227 }
14078
14079 598 static fk_option to_fk_option(dd::Foreign_key::enum_rule rule) {
14080
4/6
✓ Branch 0 taken 433 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 103 times.
✓ Branch 3 taken 41 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
598 switch (rule) {
14081 433 case dd::Foreign_key::enum_rule::RULE_NO_ACTION:
14082 433 return FK_OPTION_NO_ACTION;
14083 21 case dd::Foreign_key::enum_rule::RULE_RESTRICT:
14084 21 return FK_OPTION_RESTRICT;
14085 103 case dd::Foreign_key::enum_rule::RULE_CASCADE:
14086 103 return FK_OPTION_CASCADE;
14087 41 case dd::Foreign_key::enum_rule::RULE_SET_NULL:
14088 41 return FK_OPTION_SET_NULL;
14089 case dd::Foreign_key::enum_rule::RULE_SET_DEFAULT:
14090 return FK_OPTION_DEFAULT;
14091 }
14092 assert(false);
14093 return FK_OPTION_UNDEF;
14094 }
14095
14096 299 static fk_match_opt to_fk_match_opt(dd::Foreign_key::enum_match_option match) {
14097
1/4
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
299 switch (match) {
14098 299 case dd::Foreign_key::enum_match_option::OPTION_NONE:
14099 299 return FK_MATCH_SIMPLE;
14100 case dd::Foreign_key::enum_match_option::OPTION_PARTIAL:
14101 return FK_MATCH_PARTIAL;
14102 case dd::Foreign_key::enum_match_option::OPTION_FULL:
14103 return FK_MATCH_FULL;
14104 }
14105 assert(false);
14106 return FK_MATCH_UNDEF;
14107 }
14108
14109 1234 static void to_lex_cstring(MEM_ROOT *mem_root, LEX_CSTRING *target,
14110 const dd::String_type &source) {
14111 1234 target->str = strmake_root(mem_root, source.c_str(), source.length() + 1);
14112 1234 target->length = source.length();
14113 1234 }
14114
14115 /**
14116 Remember information about pre-existing foreign keys so
14117 that they can be added to the new version of the table later.
14118 Omit foreign keys to be dropped. Also check that the foreign
14119 keys to be kept are still valid.
14120
14121 @note This function removes pre-existing foreign keys from the
14122 drop_list, while Alter_info::drop_list is kept intact.
14123 A non-empty drop_list upon return of this function indicates
14124 an error, and means that the statement tries to drop a
14125 foreign key that did not exist in the first place.
14126
14127 @param[in] thd Thread handle.
14128 @param[in] src_table The source table.
14129 @param[in] src_db_name Original database name of table.
14130 @param[in] src_table_name Original table name of table.
14131 @param[in] hton Original storage engine.
14132 @param[in] alter_info Info about ALTER TABLE statement.
14133 @param[in] new_create_list List of new columns, used for rename check.
14134 @param[in,out] drop_list Copy of list of foreign keys to be dropped.
14135 @param[in,out] alter_ctx Runtime context for ALTER TABLE to which
14136 information about pre-existing foreign
14137 keys is added.
14138 */
14139
14140 72969 static bool transfer_preexisting_foreign_keys(
14141 THD *thd, const dd::Table *src_table, const char *src_db_name,
14142 const char *src_table_name, handlerton *hton, const Alter_info *alter_info,
14143 List<Create_field> *new_create_list, Alter_table_ctx *alter_ctx,
14144 Prealloced_array<const Alter_drop *, 1> *drop_list) {
14145
2/2
✓ Branch 0 taken 4243 times.
✓ Branch 1 taken 68726 times.
72969 if (src_table == nullptr)
14146 4243 return false; // Could be temporary table or during upgrade.
14147
14148
1/2
✓ Branch 0 taken 68726 times.
✗ Branch 1 not taken.
68726 List_iterator<Create_field> find_it(*new_create_list);
14149
14150
1/2
✓ Branch 0 taken 68726 times.
✗ Branch 1 not taken.
68726 alter_ctx->fk_info = (FOREIGN_KEY *)sql_calloc(
14151
1/2
✓ Branch 0 taken 68726 times.
✗ Branch 1 not taken.
68726 sizeof(FOREIGN_KEY) * src_table->foreign_keys().size());
14152
3/4
✓ Branch 0 taken 69084 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 364 times.
✓ Branch 3 taken 68720 times.
69084 for (size_t i = 0; i < src_table->foreign_keys().size(); i++) {
14153
2/4
✓ Branch 0 taken 364 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 364 times.
✗ Branch 3 not taken.
364 const dd::Foreign_key *dd_fk = src_table->foreign_keys()[i];
14154
14155 // Skip foreign keys that are to be dropped
14156 364 size_t k = 0;
14157
3/4
✓ Branch 0 taken 436 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 137 times.
✓ Branch 3 taken 299 times.
436 while (k < drop_list->size()) {
14158
1/2
✓ Branch 0 taken 137 times.
✗ Branch 1 not taken.
137 const Alter_drop *drop = (*drop_list)[k];
14159 // Index names are always case insensitive
14160
4/4
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 72 times.
217 if (drop->type == Alter_drop::FOREIGN_KEY &&
14161
4/6
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 65 times.
✓ Branch 5 taken 15 times.
80 my_strcasecmp(system_charset_info, drop->name,
14162 dd_fk->name().c_str()) == 0) {
14163 65 break;
14164 }
14165 72 k++;
14166 }
14167
3/4
✓ Branch 0 taken 364 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 299 times.
364 if (k < drop_list->size()) {
14168
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
65 drop_list->erase(k);
14169 65 continue;
14170 }
14171
14172 // Self-referencing foreign keys will need additional handling later.
14173 bool is_self_referencing =
14174
2/4
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 299 times.
✗ Branch 3 not taken.
299 my_strcasecmp(table_alias_charset,
14175 dd_fk->referenced_table_schema_name().c_str(),
14176
2/2
✓ Branch 0 taken 295 times.
✓ Branch 1 taken 4 times.
594 src_db_name) == 0 &&
14177
4/6
✓ Branch 0 taken 295 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 295 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 294 times.
295 my_strcasecmp(table_alias_charset,
14178 dd_fk->referenced_table_name().c_str(),
14179 299 src_table_name) == 0;
14180
14181 299 FOREIGN_KEY *sql_fk = &alter_ctx->fk_info[alter_ctx->fk_count++];
14182
14183
2/4
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 299 times.
✗ Branch 3 not taken.
299 sql_fk->name = strmake_root(thd->mem_root, dd_fk->name().c_str(),
14184
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 dd_fk->name().length() + 1);
14185
14186 299 sql_fk->unique_index_name =
14187
2/4
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 299 times.
✗ Branch 3 not taken.
299 strmake_root(thd->mem_root, dd_fk->unique_constraint_name().c_str(),
14188
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 dd_fk->unique_constraint_name().length() + 1);
14189
14190
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 sql_fk->key_parts = dd_fk->elements().size();
14191
14192
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 to_lex_cstring(thd->mem_root, &sql_fk->ref_db,
14193
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 dd_fk->referenced_table_schema_name());
14194
14195
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 to_lex_cstring(thd->mem_root, &sql_fk->ref_table,
14196
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 dd_fk->referenced_table_name());
14197
14198
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 sql_fk->delete_opt = to_fk_option(dd_fk->delete_rule());
14199
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 sql_fk->update_opt = to_fk_option(dd_fk->update_rule());
14200
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 sql_fk->match_opt = to_fk_match_opt(dd_fk->match_option());
14201
14202 299 sql_fk->key_part =
14203
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 (LEX_CSTRING *)sql_calloc(sizeof(LEX_CSTRING) * sql_fk->key_parts);
14204 299 sql_fk->fk_key_part =
14205
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 (LEX_CSTRING *)sql_calloc(sizeof(LEX_CSTRING) * sql_fk->key_parts);
14206
14207
2/2
✓ Branch 0 taken 334 times.
✓ Branch 1 taken 293 times.
627 for (size_t j = 0; j < sql_fk->key_parts; j++) {
14208
2/4
✓ Branch 0 taken 334 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 334 times.
✗ Branch 3 not taken.
334 const dd::Foreign_key_element *dd_fk_ele = dd_fk->elements()[j];
14209
14210
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 319 times.
334 if (alter_info->flags & Alter_info::ALTER_DROP_COLUMN) {
14211 /* Check if column used in the foreign key was dropped. */
14212
4/6
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 9 times.
15 if (std::any_of(
14213 alter_info->drop_list.cbegin(), alter_info->drop_list.cend(),
14214 30 [dd_fk_ele](const Alter_drop *drop) {
14215
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
30 return drop->type == Alter_drop::COLUMN &&
14216
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
30 !my_strcasecmp(system_charset_info,
14217 dd_fk_ele->column().name().c_str(),
14218 drop->name);
14219 })) {
14220
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(ER_FK_COLUMN_CANNOT_DROP, MYF(0),
14221
3/6
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
6 dd_fk_ele->column().name().c_str(), dd_fk->name().c_str());
14222 6 return true;
14223 }
14224
14225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (is_self_referencing) {
14226 /*
14227 Do the same check for referenced column if child and parent
14228 table are the same.
14229 */
14230 find_it.rewind();
14231 const Create_field *find;
14232 while ((find = find_it++)) {
14233 if (find->field &&
14234 my_strcasecmp(system_charset_info,
14235 dd_fk_ele->referenced_column_name().c_str(),
14236 find->field->field_name) == 0) {
14237 break;
14238 }
14239 }
14240 if (find == nullptr) {
14241 my_error(ER_FK_COLUMN_CANNOT_DROP_CHILD, MYF(0),
14242 dd_fk_ele->referenced_column_name().c_str(),
14243 dd_fk->name().c_str(), dd_fk->table().name().c_str());
14244 return true;
14245 }
14246 }
14247 }
14248
14249 // Check if the column was renamed by the same statement.
14250 328 bool col_renamed = false;
14251 328 bool ref_col_renamed = false;
14252
14253
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 243 times.
328 if (alter_info->flags & Alter_info::ALTER_CHANGE_COLUMN) {
14254 85 find_it.rewind();
14255 const Create_field *find;
14256
6/6
✓ Branch 0 taken 405 times.
✓ Branch 1 taken 75 times.
✓ Branch 2 taken 395 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 395 times.
✓ Branch 5 taken 85 times.
480 while ((find = find_it++) && !col_renamed) {
14257
9/12
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 294 times.
✓ Branch 2 taken 101 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 101 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 101 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 20 times.
✓ Branch 9 taken 81 times.
✓ Branch 10 taken 20 times.
✓ Branch 11 taken 375 times.
395 if (find->change && my_strcasecmp(system_charset_info,
14258 dd_fk_ele->column().name().c_str(),
14259 find->change) == 0) {
14260 // Use new name
14261 20 sql_fk->key_part[j].str = find->field_name;
14262 20 sql_fk->key_part[j].length = strlen(find->field_name);
14263 20 col_renamed = true;
14264 }
14265 }
14266
14267 /*
14268 If foreign key has the same table as child and parent we also
14269 need to update names of referenced columns if they are renamed.
14270 */
14271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 if (is_self_referencing) {
14272 find_it.rewind();
14273 while ((find = find_it++) && !ref_col_renamed) {
14274 if (find->change &&
14275 my_strcasecmp(system_charset_info,
14276 dd_fk_ele->referenced_column_name().c_str(),
14277 find->change) == 0) {
14278 // Use new name
14279 sql_fk->fk_key_part[j].str = find->field_name;
14280 sql_fk->fk_key_part[j].length = strlen(find->field_name);
14281 ref_col_renamed = true;
14282 }
14283 }
14284 }
14285 }
14286
2/2
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 20 times.
328 if (!col_renamed) // Use old name
14287
1/2
✓ Branch 0 taken 308 times.
✗ Branch 1 not taken.
308 to_lex_cstring(thd->mem_root, &sql_fk->key_part[j],
14288
2/4
✓ Branch 0 taken 308 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 308 times.
✗ Branch 3 not taken.
308 dd_fk_ele->column().name());
14289
14290
1/2
✓ Branch 0 taken 328 times.
✗ Branch 1 not taken.
328 if (!ref_col_renamed)
14291
1/2
✓ Branch 0 taken 328 times.
✗ Branch 1 not taken.
328 to_lex_cstring(thd->mem_root, &sql_fk->fk_key_part[j],
14292
1/2
✓ Branch 0 taken 328 times.
✗ Branch 1 not taken.
328 dd_fk_ele->referenced_column_name());
14293
14294 /*
14295 Orphan non-self-referencing FK become non-orphan/adopted
14296 self-referencing FK as a result of a table rename operation. Make sure
14297 referenced column exists and it is not a virtual column. Such FK needs
14298 additional handling later.
14299 */
14300
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 326 times.
327 if (!is_self_referencing && alter_ctx->is_table_renamed() &&
14301
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 my_strcasecmp(table_alias_charset,
14302 dd_fk->referenced_table_schema_name().c_str(),
14303
3/4
✓ Branch 0 taken 327 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 328 times.
655 alter_ctx->new_db) == 0 &&
14304
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 my_strcasecmp(table_alias_charset,
14305 dd_fk->referenced_table_name().c_str(),
14306 alter_ctx->new_name) == 0) {
14307 find_it.rewind();
14308 const Create_field *find;
14309 while ((find = find_it++)) {
14310 if (find->field &&
14311 my_strcasecmp(system_charset_info,
14312 dd_fk_ele->referenced_column_name().c_str(),
14313 find->field_name) == 0)
14314 break;
14315 }
14316 if (find == nullptr) {
14317 my_error(ER_FK_NO_COLUMN_PARENT, MYF(0), sql_fk->fk_key_part[j].str,
14318 dd_fk->name().c_str(),
14319 dd_fk->referenced_table_name().c_str());
14320 return true;
14321 }
14322 if (find->is_virtual_gcol()) {
14323 my_error(ER_FK_CANNOT_USE_VIRTUAL_COLUMN, MYF(0),
14324 dd_fk->name().c_str(), sql_fk->fk_key_part[j].str);
14325 return true;
14326 }
14327 }
14328
14329 #ifndef NDEBUG
14330 {
14331 328 find_it.rewind();
14332 Create_field *find;
14333
1/2
✓ Branch 0 taken 784 times.
✗ Branch 1 not taken.
784 while ((find = find_it++)) {
14334
1/2
✓ Branch 0 taken 784 times.
✗ Branch 1 not taken.
784 if (my_strcasecmp(system_charset_info, sql_fk->key_part[j].str,
14335
4/4
✓ Branch 0 taken 328 times.
✓ Branch 1 taken 456 times.
✓ Branch 2 taken 328 times.
✓ Branch 3 taken 456 times.
1112 find->field_name) == 0 &&
14336
1/2
✓ Branch 0 taken 328 times.
✗ Branch 1 not taken.
328 find->field != nullptr) {
14337 328 break;
14338 }
14339 }
14340 /*
14341 Thanks to the above code handling dropped columns referencing
14342 column must exist.
14343 */
14344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 328 times.
328 assert(find != nullptr);
14345 /*
14346 Also due to facts a) that we don't allow virtual columns in
14347 foreign keys and b) that existing generated columns can't be
14348 changed to virtual, referencing column must be non-virtual.
14349 */
14350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 328 times.
328 assert(!find->is_virtual_gcol());
14351
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 327 times.
328 if (is_self_referencing) {
14352 1 find_it.rewind();
14353
14354
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 while ((find = find_it++)) {
14355
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (my_strcasecmp(system_charset_info, sql_fk->fk_key_part[j].str,
14356
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 find->field_name) == 0 &&
14357
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 find->field != nullptr) {
14358 1 break;
14359 }
14360 }
14361 /*
14362 The same applies to referenced columns if foreign key has
14363 same table as child and parent.
14364 */
14365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(find != nullptr);
14366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(!find->is_virtual_gcol());
14367 }
14368 }
14369 #endif
14370 }
14371 }
14372
14373 68720 alter_ctx->fk_max_generated_name_number =
14374
1/2
✓ Branch 0 taken 68720 times.
✗ Branch 1 not taken.
68720 get_fk_max_generated_name_number(src_table_name, src_table, hton);
14375
14376 68720 return false;
14377 }
14378
14379 /**
14380 Check if the column being removed or renamed is in use by partitioning
14381 function for the table and that the partitioning is kept/partitioning
14382 function is unchanged by this ALTER TABLE, and report error if it is
14383 the case.
14384
14385 @param table TABLE object describing old table version.
14386 @param field Field object for column to be checked.
14387 @param alter_info Alter_info describing the ALTER TABLE.
14388
14389 @return
14390 true The field is used by partitioning function, error was reported.
14391 false Otherwise.
14392
14393 */
14394 3658 static bool check_if_field_used_by_partitioning_func(
14395 TABLE *table, const Field *field, const Alter_info *alter_info) {
14396 3658 partition_info *part_info = table->part_info;
14397
14398 // There is no partitioning function if table is not partitioned.
14399
2/2
✓ Branch 0 taken 3487 times.
✓ Branch 1 taken 171 times.
3658 if (!part_info) return false;
14400
14401 // Check if column is not used by (sub)partitioning function.
14402
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 24 times.
171 if (!bitmap_is_set(&part_info->full_part_field_set, field->field_index()))
14403 147 return false;
14404
14405 /*
14406 It is OK to rename/drop column that is used by old partitioning function
14407 if partitioning is removed. It is also OK to do this if partitioning for
14408 table is changed. The latter gives users a way to update partitioning
14409 function after renaming/dropping columns. Data inconsistency doesn't
14410 occur in this case as change of partitioning causes table rebuild.
14411 */
14412
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 13 times.
24 if (alter_info->flags &
14413 (Alter_info::ALTER_REMOVE_PARTITIONING | Alter_info::ALTER_PARTITION))
14414 11 return false;
14415
14416 /*
14417 We also allow renaming and dropping of columns used by partitioning
14418 function when it is defined using PARTITION BY KEY () clause (notice
14419 empty column list). In this case partitioning function is defined by
14420 the primary key.
14421 So partitioning function stays valid when column in the primary key is
14422 renamed since the primary key is automagically adjusted in this case.
14423 Dropping column is also acceptable, as this is handled as a change of
14424 primary key (deletion of old one and addition of a new one) and storage
14425 engines are supposed to handle this correctly (at least InnoDB does
14426 thanks to fix for bug#20190520).
14427
14428 Note that we avoid complex checks and simple disallow renaming/dropping
14429 of columns if table with PARTITION BY KEY() clause is also subpartitioned.
14430 Subpartitioning by KEY always uses explicit column list so it is not safe
14431 for renaming/dropping columns.
14432 */
14433 31 if (part_info->part_type == partition_type::HASH &&
14434
7/8
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 9 times.
17 part_info->list_of_part_fields && part_info->part_field_list.is_empty() &&
14435
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 !part_info->is_sub_partitioned())
14436 4 return false;
14437
14438 9 my_error(ER_DEPENDENT_BY_PARTITION_FUNC, MYF(0), field->field_name);
14439 9 return true;
14440 }
14441
14442 /**
14443 Sets column default, drops default, renames or alters visibility.
14444 */
14445 941112 static bool alter_column_name_default_or_visibility(
14446 const Alter_info *alter_info,
14447 Prealloced_array<const Alter_column *, 1> *alter_list, Create_field *def) {
14448
1/2
✓ Branch 0 taken 941112 times.
✗ Branch 1 not taken.
941112 DBUG_TRACE;
14449
14450 // Check if ALTER TABLE has requested of such a change.
14451 941112 size_t i = 0;
14452 941112 const Alter_column *alter = nullptr;
14453
3/4
✓ Branch 0 taken 941361 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 597 times.
✓ Branch 3 taken 940764 times.
941361 while (i < alter_list->size()) {
14454
1/2
✓ Branch 0 taken 597 times.
✗ Branch 1 not taken.
597 alter = (*alter_list)[i];
14455
3/4
✓ Branch 0 taken 597 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 348 times.
✓ Branch 3 taken 249 times.
597 if (!my_strcasecmp(system_charset_info, def->field_name, alter->name))
14456 348 break;
14457 249 i++;
14458 }
14459
14460 // Nothing changed.
14461
3/4
✓ Branch 0 taken 941112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 940764 times.
✓ Branch 3 taken 348 times.
941112 if (i == alter_list->size()) return false;
14462
14463 // Setup the field.
14464
5/6
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 84 times.
✓ Branch 2 taken 89 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
348 switch (alter->change_type()) {
14465 144 case Alter_column::Type::SET_DEFAULT: {
14466
3/4
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
144 assert(alter->def || alter->m_default_val_expr);
14467
14468 // Assign new default.
14469 144 def->constant_default = alter->def;
14470 144 def->m_default_val_expr = alter->m_default_val_expr;
14471
14472
3/4
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 90 times.
144 if (alter->def && def->flags & BLOB_FLAG) {
14473 my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->field_name);
14474 return true;
14475 }
14476
14477
4/4
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 120 times.
198 if (alter->m_default_val_expr != nullptr &&
14478
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 30 times.
54 pre_validate_value_generator_expr(
14479
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 alter->m_default_val_expr->expr_item, alter->name,
14480 VGS_DEFAULT_EXPRESSION))
14481 24 return true;
14482
14483 // Default value is not permitted for generated columns
14484
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 118 times.
120 if (def->field->is_gcol()) {
14485
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_WRONG_USAGE, MYF(0), "DEFAULT", "generated column");
14486 2 return true;
14487 }
14488
14489 118 def->flags &= ~NO_DEFAULT_VALUE_FLAG;
14490 /*
14491 The defaults are explicitly altered for the TIMESTAMP/DATETIME
14492 field, through SET DEFAULT. Hence, set the auto_flags member
14493 appropriately.
14494 */
14495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118 times.
118 if (real_type_with_now_as_default(def->sql_type)) {
14496 assert((def->auto_flags & ~(Field::DEFAULT_NOW | Field::ON_UPDATE_NOW |
14497 Field::GENERATED_FROM_EXPRESSION)) == 0);
14498 def->auto_flags &= ~Field::DEFAULT_NOW;
14499 }
14500 /*
14501 Columns can't have AUTO_INCREMENT and DEFAULT/ON UPDATE
14502 CURRENT_TIMESTAMP/ default from expression the same time.
14503 */
14504
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 110 times.
118 if ((def->auto_flags & Field::NEXT_NUMBER) != 0 &&
14505
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 ((def->auto_flags & (Field::DEFAULT_NOW | Field::ON_UPDATE_NOW)) !=
14506 8 0 ||
14507
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 def->m_default_val_expr != nullptr)) {
14508
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_INVALID_DEFAULT, MYF(0), def->field_name);
14509 4 return true;
14510 }
14511 114 } break;
14512
14513 84 case Alter_column::Type::DROP_DEFAULT: {
14514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 assert(!alter->def);
14515
14516 // Mark field to have no default.
14517 84 def->constant_default = nullptr;
14518 84 def->m_default_val_expr = nullptr;
14519 84 def->flags |= NO_DEFAULT_VALUE_FLAG;
14520 84 } break;
14521
14522 89 case Alter_column::Type::RENAME_COLUMN: {
14523 89 def->change = alter->name;
14524 89 def->field_name = alter->m_new_name;
14525
14526 /*
14527 If a generated column or a default expression is dependent
14528 on this column, this column cannot be renamed.
14529
14530 The same applies to case when this table is partitioned and
14531 partitioning function is dependent on column being renamed.
14532 */
14533 267 if (check_if_field_used_by_generated_column_or_default(
14534
5/6
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 83 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 79 times.
172 def->field->table, def->field, alter_info) ||
14535
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 79 times.
83 check_if_field_used_by_partitioning_func(def->field->table,
14536
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 def->field, alter_info))
14537 10 return true;
14538 79 } break;
14539
14540 16 case Alter_column::Type::SET_COLUMN_VISIBLE:
14541 16 def->hidden = dd::Column::enum_hidden_type::HT_VISIBLE;
14542 16 break;
14543
14544 15 case Alter_column::Type::SET_COLUMN_INVISIBLE:
14545 15 def->hidden = dd::Column::enum_hidden_type::HT_HIDDEN_USER;
14546 15 break;
14547
14548 default:
14549 assert(0);
14550 my_error(ER_UNKNOWN_ERROR, MYF(0));
14551 return true;
14552 }
14553
14554 // Remove the element from to be altered column list.
14555
1/2
✓ Branch 0 taken 308 times.
✗ Branch 1 not taken.
308 alter_list->erase(i);
14556
14557 308 return false;
14558 941112 }
14559
14560 /**
14561 Check if the column being removed or renamed is in use by a generated
14562 column, default or functional index, which will be kept around/unchanged
14563 by this ALTER TABLE, and report error which is appropriate for the case.
14564
14565 @param table TABLE object describing old table version.
14566 @param field Field object for column to be checked.
14567 @param alter_info Alter_info describing which columns, defaults or
14568 indexes are dropped or modified.
14569
14570 @return
14571 true The field is used by generated column/default or functional
14572 index, error was reported.
14573 false Otherwise.
14574
14575 */
14576 3676 static bool check_if_field_used_by_generated_column_or_default(
14577 TABLE *table, const Field *field, const Alter_info *alter_info) {
14578 3676 MY_BITMAP dependent_fields;
14579 my_bitmap_map bitbuf[bitmap_buffer_size(MAX_FIELDS) / sizeof(my_bitmap_map)];
14580
1/2
✓ Branch 0 taken 3676 times.
✗ Branch 1 not taken.
3676 bitmap_init(&dependent_fields, bitbuf, table->s->fields);
14581 3676 MY_BITMAP *save_old_read_set = table->read_set;
14582 3676 table->read_set = &dependent_fields;
14583
14584
2/2
✓ Branch 0 taken 21091 times.
✓ Branch 1 taken 3658 times.
24749 for (Field **vfield_ptr = table->field; *vfield_ptr; vfield_ptr++) {
14585 21091 Field *vfield = *vfield_ptr;
14586
6/6
✓ Branch 0 taken 20053 times.
✓ Branch 1 taken 1038 times.
✓ Branch 2 taken 202 times.
✓ Branch 3 taken 19851 times.
✓ Branch 4 taken 1240 times.
✓ Branch 5 taken 19851 times.
41144 if (vfield->is_gcol() ||
14587 20053 vfield->has_insert_default_general_value_expression()) {
14588 /*
14589 Ignore generated columns (including hidden columns for functional
14590 indexes) and columns with generated defaults which are going to
14591 be dropped.
14592 */
14593
4/6
✓ Branch 0 taken 1240 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1240 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 325 times.
✓ Branch 5 taken 915 times.
1240 if (std::any_of(alter_info->drop_list.cbegin(),
14594 alter_info->drop_list.cend(),
14595 2872 [vfield](const Alter_drop *drop) {
14596
2/2
✓ Branch 0 taken 1100 times.
✓ Branch 1 taken 672 times.
2872 return drop->type == Alter_drop::COLUMN &&
14597
2/2
✓ Branch 0 taken 325 times.
✓ Branch 1 taken 775 times.
2872 !my_strcasecmp(system_charset_info,
14598 vfield->field_name, drop->name);
14599 }))
14600 351 continue;
14601
14602 /*
14603 Ignore generated default values which are removed or changed.
14604
14605 If new default value is dependent on removed/renamed column
14606 the problem will be detected and reported as error later.
14607 */
14608
3/4
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 731 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 915 times.
1099 if (vfield->has_insert_default_general_value_expression() &&
14609
4/8
✓ Branch 0 taken 184 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 184 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 184 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 184 times.
184 std::any_of(alter_info->alter_list.cbegin(),
14610 alter_info->alter_list.cend(),
14611 4 [vfield](const Alter_column *alter) {
14612 4 return (alter->change_type() ==
14613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 Alter_column::Type::SET_DEFAULT ||
14614 4 alter->change_type() ==
14615
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
8 Alter_column::Type::DROP_DEFAULT) &&
14616
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
4 !my_strcasecmp(system_charset_info,
14617 vfield->field_name, alter->name);
14618 }))
14619 continue;
14620
14621 /*
14622 Ignore columns which are explicitly mentioned in CHANGE/MODIFY
14623 clauses in this ALTER TABLE and thus have new generation expression
14624 or default.
14625
14626 Again if such new expression is dependent on removed/renamed column
14627 the problem will be detected and reported as error later.
14628 */
14629
5/8
✓ Branch 0 taken 915 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 915 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 915 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 26 times.
✓ Branch 7 taken 889 times.
915 if (std::any_of(alter_info->create_list.cbegin(),
14630 alter_info->create_list.cend(),
14631 424 [vfield](const Create_field &def) {
14632
2/2
✓ Branch 0 taken 191 times.
✓ Branch 1 taken 42 times.
424 return (def.change &&
14633
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 165 times.
191 !my_strcasecmp(system_charset_info,
14634 233 vfield->field_name, def.change));
14635 }))
14636 26 continue;
14637
14638
5/8
✓ Branch 0 taken 709 times.
✓ Branch 1 taken 180 times.
✓ Branch 2 taken 709 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 180 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 180 times.
✗ Branch 7 not taken.
889 assert((vfield->gcol_info && vfield->gcol_info->expr_item) ||
14639 (vfield->m_default_val_expr &&
14640 vfield->m_default_val_expr->expr_item));
14641 889 Mark_field mark_fld(MARK_COLUMNS_TEMP);
14642
2/2
✓ Branch 0 taken 709 times.
✓ Branch 1 taken 180 times.
889 Item *expr = vfield->is_gcol() ? vfield->gcol_info->expr_item
14643 180 : vfield->m_default_val_expr->expr_item;
14644
1/2
✓ Branch 0 taken 889 times.
✗ Branch 1 not taken.
889 expr->walk(&Item::mark_field_in_map, enum_walk::PREFIX,
14645 reinterpret_cast<uchar *>(&mark_fld));
14646
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 871 times.
889 if (bitmap_is_set(table->read_set, field->field_index())) {
14647
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
18 if (vfield->is_gcol()) {
14648
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (vfield->is_field_for_functional_index())
14649 2 my_error(ER_DEPENDENT_BY_FUNCTIONAL_INDEX, MYF(0),
14650
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 field->field_name);
14651 else
14652 4 my_error(ER_DEPENDENT_BY_GENERATED_COLUMN, MYF(0),
14653
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 field->field_name);
14654 } else {
14655 12 my_error(ER_DEPENDENT_BY_DEFAULT_GENERATED_VALUE, MYF(0),
14656
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 field->field_name, table->alias);
14657 }
14658 18 table->read_set = save_old_read_set;
14659 18 return true;
14660 }
14661 }
14662 }
14663
14664 3658 table->read_set = save_old_read_set;
14665 3658 return false;
14666 }
14667
14668 // Prepare Create_field and Key_spec objects for ALTER and upgrade.
14669 95231 bool prepare_fields_and_keys(THD *thd, const dd::Table *src_table, TABLE *table,
14670 HA_CREATE_INFO *create_info,
14671 Alter_info *alter_info, Alter_table_ctx *alter_ctx,
14672 const uint &used_fields) {
14673 /* New column definitions are added here */
14674 95231 List<Create_field> new_create_list;
14675 /* New key definitions are added here */
14676
1/2
✓ Branch 0 taken 95231 times.
✗ Branch 1 not taken.
95231 Mem_root_array<Key_spec *> new_key_list(thd->mem_root);
14677
14678 /*
14679 Original Alter_info::drop_list is used by foreign key handling code and
14680 storage engines. check_if_field_used_by_generated_column_or_default()
14681 also needs original Alter_info::drop_list. So this function should not
14682 modify original list but rather work with its copy.
14683 */
14684 Prealloced_array<const Alter_drop *, 1> drop_list(
14685 PSI_INSTRUMENT_ME, alter_info->drop_list.cbegin(),
14686
2/4
✓ Branch 0 taken 95231 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95231 times.
✗ Branch 3 not taken.
95231 alter_info->drop_list.cend());
14687
14688 /*
14689 Alter_info::alter_rename_key_list is also used by fill_alter_inplace_info()
14690 call. So this function should not modify original list but rather work with
14691 its copy.
14692 */
14693 Prealloced_array<const Alter_rename_key *, 1> rename_key_list(
14694 PSI_INSTRUMENT_ME, alter_info->alter_rename_key_list.cbegin(),
14695
3/6
✓ Branch 0 taken 95231 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95231 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 95231 times.
✗ Branch 5 not taken.
95231 alter_info->alter_rename_key_list.cend());
14696
14697 /*
14698 This is how we check that all indexes to be altered are name-resolved: We
14699 make a copy of the list from the alter_info, and remove all the indexes
14700 that are found in the table. Later we check that there is nothing left in
14701 the list. This is obviously just a copy-paste of what is done for renamed
14702 indexes.
14703 */
14704 Prealloced_array<const Alter_index_visibility *, 1> index_visibility_list(
14705 PSI_INSTRUMENT_ME, alter_info->alter_index_visibility_list.cbegin(),
14706
3/6
✓ Branch 0 taken 95231 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95231 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 95231 times.
✗ Branch 5 not taken.
95231 alter_info->alter_index_visibility_list.cend());
14707
14708 /* List with secondary keys which should be created after copying the data */
14709
1/2
✓ Branch 0 taken 95231 times.
✗ Branch 1 not taken.
95231 Mem_root_array<const Key_spec *> delayed_key_list(thd->mem_root);
14710 /*
14711 Alter_info::alter_list is used by fill_alter_inplace_info() call as well.
14712 So this function works on its copy rather than original list.
14713 */
14714 Prealloced_array<const Alter_column *, 1> alter_list(
14715 PSI_INSTRUMENT_ME, alter_info->alter_list.cbegin(),
14716
3/6
✓ Branch 0 taken 95231 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 95231 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 95231 times.
✗ Branch 5 not taken.
95231 alter_info->alter_list.cend());
14717
14718
1/2
✓ Branch 0 taken 95231 times.
✗ Branch 1 not taken.
95231 List_iterator<Create_field> def_it(alter_info->create_list);
14719
1/2
✓ Branch 0 taken 95231 times.
✗ Branch 1 not taken.
95231 List_iterator<Create_field> find_it(new_create_list);
14720
1/2
✓ Branch 0 taken 95231 times.
✗ Branch 1 not taken.
95231 List_iterator<Create_field> field_it(new_create_list);
14721 95231 List<Key_part_spec> key_parts;
14722 95231 KEY *key_info = table->key_info;
14723
14724
1/2
✓ Branch 0 taken 95231 times.
✗ Branch 1 not taken.
95231 DBUG_TRACE;
14725
14726 /*
14727 During upgrade from 5.7, old tables are temporarily accessed to
14728 get the keys and fields, and in this process, we assign
14729 table->record[0] = table->s->default_values, hence, we make the
14730 call to restore_record() below conditional to avoid valgrind errors
14731 due to overlapping source and destination for memcpy.
14732 */
14733
2/2
✓ Branch 0 taken 90926 times.
✓ Branch 1 taken 4305 times.
95231 if (table->record[0] != table->s->default_values)
14734 90926 restore_record(table, s->default_values); // Empty record for DEFAULT
14735
14736 95231 std::vector<Create_field *> functional_index_columns;
14737 Create_field *def;
14738
14739 /*
14740 First collect all fields from table which isn't in drop_list
14741 */
14742 Field **f_ptr, *field;
14743
2/2
✓ Branch 0 taken 974403 times.
✓ Branch 1 taken 95171 times.
1069574 for (f_ptr = table->field; (field = *f_ptr); f_ptr++) {
14744 /* Check if field should be dropped */
14745 974403 size_t i = 0;
14746
3/4
✓ Branch 0 taken 1021025 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49787 times.
✓ Branch 3 taken 971238 times.
1021025 while (i < drop_list.size()) {
14747
1/2
✓ Branch 0 taken 49787 times.
✗ Branch 1 not taken.
49787 const Alter_drop *drop = drop_list[i];
14748
4/4
✓ Branch 0 taken 12387 times.
✓ Branch 1 taken 37400 times.
✓ Branch 2 taken 3165 times.
✓ Branch 3 taken 46622 times.
62174 if (drop->type == Alter_drop::COLUMN &&
14749
3/4
✓ Branch 0 taken 12387 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3165 times.
✓ Branch 3 taken 9222 times.
12387 !my_strcasecmp(system_charset_info, field->field_name, drop->name)) {
14750 /* Reset auto_increment value if it was dropped */
14751
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3130 times.
3165 if ((field->auto_flags & Field::NEXT_NUMBER) &&
14752
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 6 times.
35 !(used_fields & HA_CREATE_USED_AUTO)) {
14753 29 create_info->auto_increment_value = 0;
14754 29 create_info->used_fields |= HA_CREATE_USED_AUTO;
14755 }
14756
14757 /*
14758 If a generated column or a default expression is dependent
14759 on this column, this column cannot be dropped.
14760
14761 The same applies to case when this table is partitioned and
14762 we drop column used by partitioning function.
14763 */
14764
1/2
✓ Branch 0 taken 3165 times.
✗ Branch 1 not taken.
3165 if (check_if_field_used_by_generated_column_or_default(table, field,
14765
4/4
✓ Branch 0 taken 3158 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 3155 times.
6323 alter_info) ||
14766
3/4
✓ Branch 0 taken 3158 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3155 times.
3158 check_if_field_used_by_partitioning_func(table, field, alter_info))
14767 10 return true;
14768
14769 3155 break; // Column was found.
14770 }
14771 46622 i++;
14772 }
14773
3/4
✓ Branch 0 taken 974393 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3155 times.
✓ Branch 3 taken 971238 times.
974393 if (i < drop_list.size()) {
14774
1/2
✓ Branch 0 taken 3155 times.
✗ Branch 1 not taken.
3155 drop_list.erase(i);
14775 3155 continue;
14776 }
14777 /* Check if field is changed */
14778 971238 def_it.rewind();
14779
2/2
✓ Branch 0 taken 1133325 times.
✓ Branch 1 taken 941112 times.
2074437 while ((def = def_it++)) {
14780
4/4
✓ Branch 0 taken 587786 times.
✓ Branch 1 taken 545539 times.
✓ Branch 2 taken 30126 times.
✓ Branch 3 taken 1103199 times.
1721111 if (def->change &&
14781
3/4
✓ Branch 0 taken 587786 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30126 times.
✓ Branch 3 taken 557660 times.
587786 !my_strcasecmp(system_charset_info, field->field_name, def->change))
14782 30126 break;
14783 }
14784
2/2
✓ Branch 0 taken 30126 times.
✓ Branch 1 taken 941112 times.
971238 if (def) { // Field is changed
14785 30126 def->field = field;
14786
1/2
✓ Branch 0 taken 30126 times.
✗ Branch 1 not taken.
30126 def->charset = get_sql_field_charset(def, create_info);
14787
14788
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 30123 times.
30126 if (field->stored_in_db != def->stored_in_db) {
14789
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN, MYF(0),
14790 "Changing the STORED status");
14791 3 return true;
14792 }
14793
14794 /*
14795 If a generated column or a default expression is dependent
14796 on this column, this column cannot be renamed.
14797
14798 The same applies to case when this table is partitioned and
14799 we rename column used by partitioning function.
14800 */
14801
1/2
✓ Branch 0 taken 30123 times.
✗ Branch 1 not taken.
30123 if ((my_strcasecmp(system_charset_info, def->field_name, def->change) !=
14802
4/4
✓ Branch 0 taken 422 times.
✓ Branch 1 taken 29701 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 30116 times.
30545 0) &&
14803
3/4
✓ Branch 0 taken 422 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 417 times.
✓ Branch 3 taken 5 times.
422 (check_if_field_used_by_generated_column_or_default(table, field,
14804 417 alter_info) ||
14805
3/4
✓ Branch 0 taken 417 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 415 times.
417 check_if_field_used_by_partitioning_func(table, field, alter_info)))
14806 7 return true;
14807
14808 /*
14809 Add column being updated to the list of new columns.
14810 Note that columns with AFTER clauses are added to the end
14811 of the list for now. Their positions will be corrected later.
14812 */
14813
1/2
✓ Branch 0 taken 30116 times.
✗ Branch 1 not taken.
30116 new_create_list.push_back(def);
14814
14815 /*
14816 If the new column type is GEOMETRY (or a subtype) NOT NULL,
14817 and the old column type is nullable and not GEOMETRY (or a
14818 subtype), existing NULL values will be converted into empty
14819 strings in non-strict mode. Empty strings are illegal values
14820 in GEOMETRY columns.
14821
14822 However, generated columns have implicit default values, so they can be
14823 NOT NULL.
14824 */
14825 60356 if (def->sql_type == MYSQL_TYPE_GEOMETRY &&
14826
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 61 times.
124 (def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
14827
5/6
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 48 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 2 times.
63 field->type() != MYSQL_TYPE_GEOMETRY && field->is_nullable() &&
14828
8/8
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 29992 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 30112 times.
30240 !thd->is_strict_mode() && !def->is_gcol()) {
14829 4 alter_ctx->error_if_not_empty |=
14830 Alter_table_ctx::GEOMETRY_WITHOUT_DEFAULT;
14831 }
14832 } else {
14833 /*
14834 This field was not dropped and the definition is not changed, add
14835 it to the list for the new table.
14836 */
14837
2/4
✓ Branch 0 taken 941112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 941112 times.
✗ Branch 3 not taken.
941112 def = new (thd->mem_root) Create_field(field, field);
14838
14839 // Mark if collation was specified explicitly by user for the column.
14840 941112 const dd::Table *obj =
14841
2/2
✓ Branch 0 taken 8232 times.
✓ Branch 1 taken 932880 times.
941112 (table->s->tmp_table ? table->s->tmp_table_def : src_table);
14842 // In case of upgrade, we do not have src_table.
14843
2/2
✓ Branch 0 taken 27852 times.
✓ Branch 1 taken 913260 times.
941112 if (!obj)
14844 27852 def->is_explicit_collation = false;
14845 else
14846 1826520 def->is_explicit_collation =
14847
3/6
✓ Branch 0 taken 913260 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 913260 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 913260 times.
✗ Branch 5 not taken.
913260 obj->get_column(field->field_name)->is_explicit_collation();
14848
14849 // If we have a replication setup _and_ the master doesn't sort
14850 // functional index columns last in the table, we will not do it either.
14851 // Otherwise, we will position the functional index columns last in the
14852 // table, sorted on their name.
14853
7/8
✓ Branch 0 taken 941112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 314 times.
✓ Branch 3 taken 940798 times.
✓ Branch 4 taken 313 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 313 times.
✓ Branch 7 taken 940799 times.
941426 if (is_field_for_functional_index(def) &&
14854 314 is_not_slave_or_master_sorts_functional_index_columns_last(
14855 thd->variables.original_server_version)) {
14856
1/2
✓ Branch 0 taken 313 times.
✗ Branch 1 not taken.
313 functional_index_columns.push_back(def);
14857 } else {
14858
1/2
✓ Branch 0 taken 940799 times.
✗ Branch 1 not taken.
940799 new_create_list.push_back(def);
14859 }
14860
14861
3/4
✓ Branch 0 taken 941112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 941072 times.
941112 if (alter_column_name_default_or_visibility(alter_info, &alter_list, def))
14862 40 return true;
14863 }
14864 }
14865 95171 def_it.rewind();
14866
2/2
✓ Branch 0 taken 61244 times.
✓ Branch 1 taken 94997 times.
156241 while ((def = def_it++)) // Add new columns
14867 {
14868
4/4
✓ Branch 0 taken 30285 times.
✓ Branch 1 taken 30959 times.
✓ Branch 2 taken 169 times.
✓ Branch 3 taken 30116 times.
61244 if (def->change && !def->field) {
14869 169 my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change,
14870
1/2
✓ Branch 0 taken 169 times.
✗ Branch 1 not taken.
169 table->s->table_name.str);
14871 169 return true;
14872 }
14873
14874
1/2
✓ Branch 0 taken 61075 times.
✗ Branch 1 not taken.
61075 warn_on_deprecated_float_auto_increment(thd, *def);
14875
14876 /*
14877 If this ALTER TABLE doesn't have an AFTER clause for the modified
14878 column then it doesn't need further processing.
14879 */
14880
4/4
✓ Branch 0 taken 30116 times.
✓ Branch 1 taken 30959 times.
✓ Branch 2 taken 26168 times.
✓ Branch 3 taken 3948 times.
61075 if (def->change && !def->after) continue;
14881
14882 /*
14883 New columns of type DATE/DATETIME/GEOMETRIC with NOT NULL constraint
14884 added as part of ALTER operation will generate zero date for DATE/
14885 DATETIME types and empty string for GEOMETRIC types when the table
14886 is not empty. Hence certain additional checks needs to be performed
14887 as described below. This cannot be caught by SE(For INPLACE ALTER)
14888 since it checks for only NULL value. Zero date and empty string
14889 does not violate the NOT NULL value constraint.
14890 */
14891
2/2
✓ Branch 0 taken 30959 times.
✓ Branch 1 taken 3948 times.
34907 if (!def->change) {
14892 /*
14893 Check that the DATE/DATETIME NOT NULL field we are going to
14894 add either has a default value, is a generated column, or the
14895 date '0000-00-00' is allowed by the set sql mode.
14896
14897 If the '0000-00-00' value isn't allowed then raise the
14898 error_if_not_empty flag to allow ALTER TABLE only if the table to be
14899 altered is empty.
14900 */
14901 92877 if ((def->sql_type == MYSQL_TYPE_DATE ||
14902
2/2
✓ Branch 0 taken 30757 times.
✓ Branch 1 taken 202 times.
30959 def->sql_type == MYSQL_TYPE_NEWDATE ||
14903
1/2
✓ Branch 0 taken 30757 times.
✗ Branch 1 not taken.
30757 def->sql_type == MYSQL_TYPE_DATETIME ||
14904
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 30689 times.
30757 def->sql_type == MYSQL_TYPE_DATETIME2) &&
14905
7/8
✓ Branch 0 taken 30959 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 268 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 256 times.
✓ Branch 5 taken 12 times.
✓ Branch 6 taken 111 times.
✓ Branch 7 taken 30848 times.
62174 !alter_ctx->datetime_field && !def->is_gcol() &&
14906
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 145 times.
256 !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG))) {
14907 111 alter_ctx->datetime_field = def;
14908 111 alter_ctx->error_if_not_empty |=
14909 Alter_table_ctx::DATETIME_WITHOUT_DEFAULT;
14910 }
14911
14912 /*
14913 New GEOMETRY (and subtypes) columns can't be NOT NULL unless they have a
14914 default value. Explicit default values are currently not supported for
14915 geometry columns. To add a GEOMETRY NOT NULL column, first create a
14916 GEOMETRY NULL column, UPDATE the table to set a different value than
14917 NULL, and then do a ALTER TABLE MODIFY COLUMN to set NOT NULL.
14918
14919 This restriction can be lifted once MySQL supports explicit default
14920 values (i.e., functions) for geometry columns. The new restriction would
14921 then be for added GEOMETRY NOT NULL columns to always have a provided
14922 default value.
14923
14924 Generated columns (including generated geometry columns) have implicit
14925 default values, so they can be NOT NULL.
14926 */
14927
6/6
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 30882 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 41 times.
✓ Branch 4 taken 26 times.
✓ Branch 5 taken 30933 times.
30995 if (def->sql_type == MYSQL_TYPE_GEOMETRY && !def->is_gcol() &&
14928
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 10 times.
36 (def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG))) {
14929 26 alter_ctx->error_if_not_empty |=
14930 Alter_table_ctx::GEOMETRY_WITHOUT_DEFAULT;
14931 }
14932 }
14933
14934
2/2
✓ Branch 0 taken 21359 times.
✓ Branch 1 taken 13548 times.
34907 if (!def->after)
14935
1/2
✓ Branch 0 taken 21359 times.
✗ Branch 1 not taken.
21359 new_create_list.push_back(def);
14936 else {
14937 const Create_field *find;
14938
2/2
✓ Branch 0 taken 3948 times.
✓ Branch 1 taken 9600 times.
13548 if (def->change) {
14939 3948 find_it.rewind();
14940 /*
14941 For columns being modified with AFTER clause we should first remove
14942 these columns from the list and then add them back at their correct
14943 positions.
14944 */
14945
1/2
✓ Branch 0 taken 100999 times.
✗ Branch 1 not taken.
100999 while ((find = find_it++)) {
14946 /*
14947 Create_fields representing changed columns are added directly
14948 from Alter_info::create_list to new_create_list. We can therefore
14949 safely use pointer equality rather than name matching here.
14950 This prevents removing the wrong column in case of column rename.
14951 */
14952
2/2
✓ Branch 0 taken 3948 times.
✓ Branch 1 taken 97051 times.
100999 if (find == def) {
14953
1/2
✓ Branch 0 taken 3948 times.
✗ Branch 1 not taken.
3948 find_it.remove();
14954 3948 break;
14955 }
14956 }
14957 }
14958
2/2
✓ Branch 0 taken 1759 times.
✓ Branch 1 taken 11789 times.
13548 if (def->after == first_keyword)
14959
1/2
✓ Branch 0 taken 1759 times.
✗ Branch 1 not taken.
1759 new_create_list.push_front(def);
14960 else {
14961 11789 find_it.rewind();
14962
2/2
✓ Branch 0 taken 250135 times.
✓ Branch 1 taken 5 times.
250140 while ((find = find_it++)) {
14963
3/4
✓ Branch 0 taken 250135 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11784 times.
✓ Branch 3 taken 238351 times.
250135 if (!my_strcasecmp(system_charset_info, def->after, find->field_name))
14964 11784 break;
14965 }
14966
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 11784 times.
11789 if (!find) {
14967 5 my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after,
14968
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 table->s->table_name.str);
14969 5 return true;
14970 }
14971
1/2
✓ Branch 0 taken 11784 times.
✗ Branch 1 not taken.
11784 find_it.after(def); // Put column after this
14972 }
14973 }
14974 }
14975
3/4
✓ Branch 0 taken 94997 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 94993 times.
94997 if (alter_list.size() > 0) {
14976
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_BAD_FIELD_ERROR, MYF(0), alter_list[0]->name,
14977
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 table->s->table_name.str);
14978 4 return true;
14979 }
14980
14981 // Ensure that hidden generated column for functional indexes are inserted at
14982 // the end, sorted by their column name.
14983
1/2
✓ Branch 0 taken 94993 times.
✗ Branch 1 not taken.
94993 std::sort(functional_index_columns.begin(), functional_index_columns.end(),
14984 354 [](const Create_field *a, const Create_field *b) {
14985 354 return my_strcasecmp(system_charset_info, a->field_name,
14986 354 b->field_name) < 0;
14987 });
14988
14989
2/2
✓ Branch 0 taken 313 times.
✓ Branch 1 taken 94993 times.
95306 for (Create_field *ic_field : functional_index_columns) {
14990
1/2
✓ Branch 0 taken 313 times.
✗ Branch 1 not taken.
313 new_create_list.push_back(ic_field);
14991 }
14992
14993
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 94953 times.
94993 if (!new_create_list.elements) {
14994
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 my_error(ER_CANT_REMOVE_ALL_FIELDS, MYF(0));
14995 40 return true;
14996 }
14997
14998 // Make sure generated invisible primary key column is at the first position.
14999
2/4
✓ Branch 0 taken 94953 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 94953 times.
94953 if (adjust_generated_invisible_primary_key_column_position(
15000 thd, create_info->db_type, table, &new_create_list))
15001 return true;
15002
15003 /*
15004 Collect all keys which isn't in drop list. Add only those
15005 for which some fields exists.
15006
15007 We also store secondary keys in delayed_key_list to make use of
15008 the InnoDB fast index creation. The following conditions must be
15009 met:
15010
15011 - fast_index_creation is enabled for the current session
15012 - expand_fast_index_creation is enabled for the current session;
15013 - we are going to create an InnoDB table (this is checked later when the
15014 target engine is known);
15015 - the key most be a non-UNIQUE one;
15016 - there are no foreign keys. This can be optimized later to exclude only
15017 those keys which are a part of foreign key constraints. Currently we
15018 simply disable this optimization for all keys if there are any foreign
15019 key constraints in the table.
15020 */
15021
15022 94953 const dd::Table *obj =
15023
2/2
✓ Branch 0 taken 1245 times.
✓ Branch 1 taken 93708 times.
94953 (table->s->tmp_table ? table->s->tmp_table_def : src_table);
15024
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 94948 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
94958 bool skip_secondary = thd->variables.expand_fast_index_creation &&
15025
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 (obj == nullptr || obj->foreign_key_parents().empty());
15026
15027
2/2
✓ Branch 0 taken 102515 times.
✓ Branch 1 taken 94950 times.
197465 for (uint i = 0; i < table->s->keys; i++, key_info++) {
15028 102515 const char *key_name = key_info->name;
15029 102515 bool index_column_dropped = false;
15030 102515 size_t drop_idx = 0;
15031
3/4
✓ Branch 0 taken 109066 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14520 times.
✓ Branch 3 taken 94546 times.
109066 while (drop_idx < drop_list.size()) {
15032
1/2
✓ Branch 0 taken 14520 times.
✗ Branch 1 not taken.
14520 const Alter_drop *drop = drop_list[drop_idx];
15033
4/4
✓ Branch 0 taken 14263 times.
✓ Branch 1 taken 257 times.
✓ Branch 2 taken 7969 times.
✓ Branch 3 taken 6551 times.
28783 if (drop->type == Alter_drop::KEY &&
15034
3/4
✓ Branch 0 taken 14263 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7969 times.
✓ Branch 3 taken 6294 times.
14263 !my_strcasecmp(system_charset_info, key_name, drop->name))
15035 7969 break;
15036 6551 drop_idx++;
15037 }
15038
3/4
✓ Branch 0 taken 102515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7969 times.
✓ Branch 3 taken 94546 times.
102515 if (drop_idx < drop_list.size()) {
15039
1/2
✓ Branch 0 taken 7969 times.
✗ Branch 1 not taken.
7969 drop_list.erase(drop_idx);
15040 7969 continue;
15041 }
15042
15043 94546 KEY_PART_INFO *key_part = key_info->key_part;
15044 94546 key_parts.clear();
15045
2/2
✓ Branch 0 taken 153400 times.
✓ Branch 1 taken 94546 times.
247946 for (uint j = 0; j < key_info->user_defined_key_parts; j++, key_part++) {
15046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 153400 times.
153400 if (!key_part->field) continue; // Wrong field (from UNIREG)
15047 153400 const char *key_part_name = key_part->field->field_name;
15048 const Create_field *cfield;
15049 153400 field_it.rewind();
15050
2/2
✓ Branch 0 taken 613582 times.
✓ Branch 1 taken 160 times.
613742 while ((cfield = field_it++)) {
15051
2/2
✓ Branch 0 taken 21073 times.
✓ Branch 1 taken 592509 times.
613582 if (cfield->change) {
15052
3/4
✓ Branch 0 taken 21073 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6579 times.
✓ Branch 3 taken 14494 times.
21073 if (!my_strcasecmp(system_charset_info, key_part_name,
15053 cfield->change))
15054 6579 break;
15055
3/4
✓ Branch 0 taken 592509 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 146661 times.
✓ Branch 3 taken 445848 times.
592509 } else if (!my_strcasecmp(system_charset_info, key_part_name,
15056 cfield->field_name))
15057 146661 break;
15058 }
15059
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 153240 times.
153400 if (!cfield) {
15060 /*
15061 We are dropping a column associated with an index.
15062 */
15063 160 index_column_dropped = true;
15064 160 continue; // Field is removed
15065 }
15066 153240 uint key_part_length = key_part->length;
15067
2/2
✓ Branch 0 taken 153071 times.
✓ Branch 1 taken 169 times.
153240 if (cfield->field) // Not new field
15068 {
15069 /*
15070 If the field can't have only a part used in a key according to its
15071 new type, or should not be used partially according to its
15072 previous type, or the field length is less than the key part
15073 length, unset the key part length.
15074
15075 We also unset the key part length if it is the same as the
15076 old field's length, so the whole new field will be used.
15077
15078 BLOBs may have cfield->length == 0, which is why we test it before
15079 checking whether cfield->length < key_part_length (in chars).
15080
15081 In case of TEXTs we check the data type maximum length *in bytes*
15082 to key part length measured *in characters* (i.e. key_part_length
15083 divided to mbmaxlen). This is because it's OK to have:
15084 CREATE TABLE t1 (a tinytext, key(a(254)) character set utf8);
15085 In case of this example:
15086 - data type maximum length is 255.
15087 - key_part_length is 1016 (=254*4, where 4 is mbmaxlen)
15088 */
15089
2/4
✓ Branch 0 taken 153071 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 153071 times.
✗ Branch 3 not taken.
153071 if (!Field::type_can_have_key_part(cfield->field->type()) ||
15090
3/4
✓ Branch 0 taken 102666 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 100823 times.
✓ Branch 3 taken 1843 times.
102666 !Field::type_can_have_key_part(cfield->sql_type) ||
15091 /* spatial keys can't have sub-key length */
15092
2/2
✓ Branch 0 taken 100691 times.
✓ Branch 1 taken 132 times.
100823 (key_info->flags & HA_SPATIAL) ||
15093
2/2
✓ Branch 0 taken 95838 times.
✓ Branch 1 taken 4853 times.
100691 (cfield->field->field_length == key_part_length &&
15094
7/8
✓ Branch 0 taken 102666 times.
✓ Branch 1 taken 50405 times.
✓ Branch 2 taken 95838 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 252 times.
✓ Branch 5 taken 95586 times.
✓ Branch 6 taken 147966 times.
✓ Branch 7 taken 5105 times.
255989 key_part->field->type() != MYSQL_TYPE_BLOB) ||
15095
2/4
✓ Branch 0 taken 5105 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5105 times.
✗ Branch 3 not taken.
5105 (cfield->max_display_width_in_codepoints() &&
15096 9975 (((cfield->sql_type >= MYSQL_TYPE_TINY_BLOB &&
15097
2/2
✓ Branch 0 taken 4809 times.
✓ Branch 1 taken 61 times.
4870 cfield->sql_type <= MYSQL_TYPE_BLOB)
15098
2/2
✓ Branch 0 taken 4870 times.
✓ Branch 1 taken 235 times.
9914 ? blob_length_by_type(cfield->sql_type)
15099
1/2
✓ Branch 0 taken 296 times.
✗ Branch 1 not taken.
296 : cfield->max_display_width_in_codepoints()) <
15100
2/4
✓ Branch 0 taken 5105 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5105 times.
5105 key_part_length / key_part->field->charset()->mbmaxlen)))
15101 147966 key_part_length = 0; // Use whole field
15102 }
15103
1/2
✓ Branch 0 taken 153240 times.
✗ Branch 1 not taken.
153240 key_part_length /= key_part->field->charset()->mbmaxlen;
15104 // The Key_part_spec constructor differentiates between explicit ascending
15105 // (ORDER_ASC) and implicit ascending order (ORDER_NOT_RELEVANT). However,
15106 // here we only have HA_REVERSE_SORT to base our ordering decision on. The
15107 // only known case where the difference matters is in case of indexes on
15108 // geometry columns and typed arrays, which can't have explicit ordering.
15109 // Therefore, in such cases we pass ORDER_NOT_RELEVANT.
15110 enum_order order =
15111 153240 key_part->key_part_flag & HA_REVERSE_SORT
15112
2/2
✓ Branch 0 taken 152844 times.
✓ Branch 1 taken 396 times.
306084 ? ORDER_DESC
15113
1/2
✓ Branch 0 taken 152844 times.
✗ Branch 1 not taken.
152844 : ((key_part->field->type() == MYSQL_TYPE_GEOMETRY ||
15114
3/4
✓ Branch 0 taken 152712 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 157 times.
✓ Branch 3 taken 152555 times.
152712 key_part->field->is_array())
15115
2/2
✓ Branch 0 taken 152712 times.
✓ Branch 1 taken 132 times.
305556 ? ORDER_NOT_RELEVANT
15116 153240 : ORDER_ASC);
15117
2/2
✓ Branch 0 taken 323 times.
✓ Branch 1 taken 152917 times.
153240 if (key_part->field->is_field_for_functional_index()) {
15118
1/2
✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
323 key_parts.push_back(new (thd->mem_root) Key_part_spec(
15119
1/2
✓ Branch 0 taken 323 times.
✗ Branch 1 not taken.
323 cfield->field_name, key_part->field->gcol_info->expr_item, order));
15120 } else {
15121
1/2
✓ Branch 0 taken 152917 times.
✗ Branch 1 not taken.
152917 key_parts.push_back(new (thd->mem_root) Key_part_spec(
15122
1/2
✓ Branch 0 taken 152917 times.
✗ Branch 1 not taken.
305834 to_lex_cstring(cfield->field_name), key_part_length, order));
15123 }
15124 }
15125
2/2
✓ Branch 0 taken 94445 times.
✓ Branch 1 taken 101 times.
94546 if (key_parts.elements) {
15126 94445 KEY_CREATE_INFO key_create_info(key_info->is_visible);
15127
15128 keytype key_type;
15129
15130 /* If this index is to stay in the table check if it has to be renamed. */
15131
3/4
✓ Branch 0 taken 94865 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 578 times.
✓ Branch 3 taken 94287 times.
94865 for (size_t rename_idx = 0; rename_idx < rename_key_list.size();
15132 rename_idx++) {
15133
1/2
✓ Branch 0 taken 578 times.
✗ Branch 1 not taken.
578 const Alter_rename_key *rename_key = rename_key_list[rename_idx];
15134
3/4
✓ Branch 0 taken 578 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 158 times.
✓ Branch 3 taken 420 times.
578 if (!my_strcasecmp(system_charset_info, key_name,
15135 rename_key->old_name)) {
15136
3/4
✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 157 times.
158 if (!my_strcasecmp(system_charset_info, key_name, primary_key_name)) {
15137
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), rename_key->old_name);
15138 3 return true;
15139
3/4
✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 156 times.
157 } else if (!my_strcasecmp(system_charset_info, rename_key->new_name,
15140 primary_key_name)) {
15141
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), rename_key->new_name);
15142 1 return true;
15143 }
15144
15145 156 key_name = rename_key->new_name;
15146
1/2
✓ Branch 0 taken 156 times.
✗ Branch 1 not taken.
156 rename_key_list.erase(rename_idx);
15147 /*
15148 If the user has explicitly renamed the key, we should no longer
15149 treat it as generated. Otherwise this key might be automatically
15150 dropped by mysql_prepare_create_table() and this will confuse
15151 code in fill_alter_inplace_info().
15152 */
15153 156 key_info->flags &= ~HA_GENERATED_KEY;
15154 156 break;
15155 }
15156 }
15157
15158 // Erase all alter operations that operate on this index.
15159
1/2
✓ Branch 0 taken 94443 times.
✗ Branch 1 not taken.
94443 for (auto it = index_visibility_list.begin();
15160
3/4
✓ Branch 0 taken 94580 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 137 times.
✓ Branch 3 taken 94443 times.
94580 it < index_visibility_list.end();)
15161
3/4
✓ Branch 0 taken 137 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 35 times.
137 if (my_strcasecmp(system_charset_info, key_name, (*it)->name()) == 0)
15162
1/2
✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
102 index_visibility_list.erase(it);
15163 else
15164 35 ++it;
15165
15166
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 94337 times.
94443 if (key_info->is_algorithm_explicit) {
15167 106 key_create_info.algorithm = key_info->algorithm;
15168 106 key_create_info.is_algorithm_explicit = true;
15169 } else {
15170 /*
15171 If key algorithm was not specified explicitly for source table
15172 don't specify one a new version as well, This allows to handle
15173 ALTER TABLEs which change SE nicely.
15174 OTOH this means that any ALTER TABLE will rebuild such keys when
15175 SE changes default algorithm for key. Code will have to be adjusted
15176 to handle such situation more gracefully.
15177 */
15178
2/4
✓ Branch 0 taken 94337 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 94337 times.
✗ Branch 3 not taken.
94337 assert((key_create_info.is_algorithm_explicit == false) &&
15179 (key_create_info.algorithm == HA_KEY_ALG_SE_SPECIFIC));
15180 }
15181
15182
2/2
✓ Branch 0 taken 261 times.
✓ Branch 1 taken 94182 times.
94443 if (key_info->flags & HA_USES_BLOCK_SIZE)
15183 261 key_create_info.block_size = key_info->block_size;
15184
2/2
✓ Branch 0 taken 873 times.
✓ Branch 1 taken 93570 times.
94443 if (key_info->flags & HA_USES_PARSER)
15185 873 key_create_info.parser_name = *plugin_name(key_info->parser);
15186
2/2
✓ Branch 0 taken 273 times.
✓ Branch 1 taken 94170 times.
94443 if (key_info->flags & HA_USES_COMMENT)
15187 273 key_create_info.comment = key_info->comment;
15188
15189
2/2
✓ Branch 0 taken 89100 times.
✓ Branch 1 taken 5343 times.
94443 if (key_info->engine_attribute.str != nullptr)
15190 89100 key_create_info.m_engine_attribute = key_info->engine_attribute;
15191
15192
2/2
✓ Branch 0 taken 89100 times.
✓ Branch 1 taken 5343 times.
94443 if (key_info->secondary_engine_attribute.str != nullptr)
15193 89100 key_create_info.m_secondary_engine_attribute =
15194 key_info->secondary_engine_attribute;
15195
15196 94589 for (const Alter_index_visibility *alter_index_visibility :
15197
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 94442 times.
189032 alter_info->alter_index_visibility_list) {
15198 147 const char *name = alter_index_visibility->name();
15199
3/4
✓ Branch 0 taken 147 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 45 times.
147 if (my_strcasecmp(system_charset_info, key_name, name) == 0) {
15200
1/2
✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
102 if (table->s->primary_key <= MAX_KEY &&
15201
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 101 times.
102 table->key_info + table->s->primary_key == key_info) {
15202
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_PK_INDEX_CANT_BE_INVISIBLE, MYF(0));
15203 1 return true;
15204 }
15205 101 key_create_info.is_visible = alter_index_visibility->is_visible();
15206 }
15207 }
15208
15209
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 94310 times.
94442 if (key_info->flags & HA_SPATIAL)
15210 132 key_type = KEYTYPE_SPATIAL;
15211
2/2
✓ Branch 0 taken 70662 times.
✓ Branch 1 taken 23648 times.
94310 else if (key_info->flags & HA_NOSAME) {
15212
3/4
✓ Branch 0 taken 70662 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57688 times.
✓ Branch 3 taken 12974 times.
70662 if (!my_strcasecmp(system_charset_info, key_name, primary_key_name))
15213 57688 key_type = KEYTYPE_PRIMARY;
15214 else
15215 12974 key_type = KEYTYPE_UNIQUE;
15216
2/2
✓ Branch 0 taken 1168 times.
✓ Branch 1 taken 22480 times.
23648 } else if (key_info->flags & HA_FULLTEXT)
15217 1168 key_type = KEYTYPE_FULLTEXT;
15218 else
15219 22480 key_type = KEYTYPE_MULTIPLE;
15220
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 94442 times.
94442 if (key_info->flags & HA_CLUSTERING)
15221 key_type = static_cast<enum keytype>(key_type | KEYTYPE_CLUSTERING);
15222
15223 /*
15224 If we have dropped a column associated with an index,
15225 this warrants a check for duplicate indexes
15226 */
15227 Key_spec *const key = new (thd->mem_root)
15228 94442 Key_spec(thd->mem_root, key_type, to_lex_cstring(key_name),
15229 94442 &key_create_info, (key_info->flags & HA_GENERATED_KEY),
15230
2/4
✓ Branch 0 taken 94442 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 94442 times.
✗ Branch 3 not taken.
94442 index_column_dropped, key_parts);
15231
1/2
✓ Branch 0 taken 94442 times.
✗ Branch 1 not taken.
94442 new_key_list.push_back(key);
15232
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 94437 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1 times.
94442 if (skip_secondary && key_type & KEYTYPE_MULTIPLE) {
15233
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 delayed_key_list.push_back(key);
15234 }
15235 }
15236 }
15237 {
15238
1/2
✓ Branch 0 taken 94950 times.
✗ Branch 1 not taken.
94950 new_key_list.reserve(new_key_list.size() + alter_info->key_list.size());
15239
2/2
✓ Branch 0 taken 17057 times.
✓ Branch 1 taken 94950 times.
112007 for (size_t i = 0; i < alter_info->key_list.size(); i++) {
15240
1/2
✓ Branch 0 taken 17057 times.
✗ Branch 1 not taken.
17057 Key_spec *const key = alter_info->key_list[i];
15241
1/2
✓ Branch 0 taken 17057 times.
✗ Branch 1 not taken.
17057 new_key_list.push_back(key); // Add new keys
15242
2/2
✓ Branch 0 taken 16803 times.
✓ Branch 1 taken 254 times.
17057 if (key->type != KEYTYPE_FOREIGN) {
15243
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 16800 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
16803 if (skip_secondary && key->type & KEYTYPE_MULTIPLE) {
15244
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 delayed_key_list.push_back(key);
15245 }
15246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 254 times.
254 } else if (skip_secondary) {
15247 /*
15248 We are adding a foreign key so disable the secondary keys
15249 optimization.
15250 */
15251 skip_secondary = false;
15252 delayed_key_list.clear();
15253 }
15254 }
15255 }
15256
15257 /*
15258 Copy existing foreign keys from the source table into
15259 Alter_table_ctx so that they can be added to the new table
15260 later. Omits foreign keys to be dropped and removes them
15261 from the drop_list. Checks that foreign keys to be kept
15262 are still valid.
15263 */
15264
2/2
✓ Branch 0 taken 72969 times.
✓ Branch 1 taken 21981 times.
94950 if (create_info->db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS) {
15265
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 72963 times.
72969 if (transfer_preexisting_foreign_keys(
15266
1/2
✓ Branch 0 taken 72969 times.
✗ Branch 1 not taken.
72969 thd, src_table, table->s->db.str, table->s->table_name.str,
15267
1/2
✓ Branch 0 taken 72969 times.
✗ Branch 1 not taken.
72969 table->s->db_type(), alter_info, &new_create_list, alter_ctx,
15268 &drop_list))
15269 6 return true;
15270 }
15271
15272
3/4
✓ Branch 0 taken 94944 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 929 times.
✓ Branch 3 taken 94015 times.
94944 if (drop_list.size() > 0) {
15273 // Now this contains only DROP for not-found objects.
15274
4/6
✓ Branch 0 taken 929 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 929 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 993 times.
✓ Branch 5 taken 54 times.
1047 for (const Alter_drop *drop : drop_list) {
15275
4/5
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 866 times.
✓ Branch 2 taken 43 times.
✓ Branch 3 taken 71 times.
✗ Branch 4 not taken.
993 switch (drop->type) {
15276 13 case Alter_drop::FOREIGN_KEY:
15277
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9 times.
13 if (!(create_info->db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS)) {
15278 /*
15279 For historical reasons we silently ignore attempts to drop
15280 foreign keys from tables in storage engines which don't
15281 support them. This is in sync with the fact that attempts
15282 to add foreign keys to such tables are silently ignored
15283 as well. Once the latter is changed the former hack can
15284 be removed as well.
15285 */
15286 4 break;
15287 }
15288 [[fallthrough]];
15289 case Alter_drop::KEY:
15290 case Alter_drop::COLUMN:
15291
1/2
✓ Branch 0 taken 875 times.
✗ Branch 1 not taken.
875 my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), drop->name);
15292 875 return true;
15293 43 case Alter_drop::CHECK_CONSTRAINT:
15294 /*
15295 Check constraints to be dropped are already handled by the
15296 prepare_check_constraints_for_alter().
15297 */
15298 43 break;
15299 71 case Alter_drop::ANY_CONSTRAINT:
15300 /*
15301 Constraint type is resolved by name and a new Alter_drop element
15302 with resolved type is added to the Alter_drop list.
15303 Alter_drop::ANY_CONSTRAINT element is retained in the Alter_drop
15304 list to support re-execution of stored routine or prepared
15305 statement.
15306 */
15307 71 break;
15308 default:
15309 assert(false);
15310 break;
15311 }
15312 }
15313 }
15314
15315
3/4
✓ Branch 0 taken 94069 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 94032 times.
94069 if (rename_key_list.size() > 0) {
15316
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), rename_key_list[0]->old_name,
15317
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 table->s->table_name.str);
15318 37 return true;
15319 }
15320
3/4
✓ Branch 0 taken 94032 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 94028 times.
94032 if (index_visibility_list.size() > 0) {
15321
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), index_visibility_list[0]->name(),
15322
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 table->s->table_name.str);
15323 4 return true;
15324 }
15325
15326 94028 alter_info->create_list.swap(new_create_list);
15327
1/2
✓ Branch 0 taken 94028 times.
✗ Branch 1 not taken.
94028 alter_info->key_list.clear();
15328
1/2
✓ Branch 0 taken 94028 times.
✗ Branch 1 not taken.
94028 alter_info->key_list.resize(new_key_list.size());
15329
1/2
✓ Branch 0 taken 94028 times.
✗ Branch 1 not taken.
94028 std::copy(new_key_list.begin(), new_key_list.end(),
15330 alter_info->key_list.begin());
15331
1/2
✓ Branch 0 taken 94028 times.
✗ Branch 1 not taken.
94028 alter_info->delayed_key_list.clear();
15332
1/2
✓ Branch 0 taken 94028 times.
✗ Branch 1 not taken.
94028 alter_info->delayed_key_list.resize(delayed_key_list.size());
15333
3/6
✓ Branch 0 taken 94028 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 94028 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 94028 times.
✗ Branch 5 not taken.
94028 std::copy(delayed_key_list.cbegin(), delayed_key_list.cend(),
15334 alter_info->delayed_key_list.begin());
15335
15336 94028 return false;
15337 95231 }
15338
15339 /**
15340 Prepare column and key definitions for CREATE TABLE in ALTER TABLE.
15341
15342 This function transforms parse output of ALTER TABLE - lists of
15343 columns and keys to add, drop or modify into, essentially,
15344 CREATE TABLE definition - a list of columns and keys of the new
15345 table. While doing so, it also performs some (bug not all)
15346 semantic checks.
15347
15348 This function is invoked when we know that we're going to
15349 perform ALTER TABLE via a temporary table -- i.e. in-place ALTER TABLE
15350 is not possible, perhaps because the ALTER statement contains
15351 instructions that require change in table data, not only in
15352 table definition or indexes.
15353
15354 @param[in,out] thd thread handle. Used as a memory pool
15355 and source of environment information.
15356 @param[in] src_table DD table object for the table to be
15357 created/altered. Will be nullptr for temporary tables.
15358 @param[in] table the source table, open and locked
15359 Used as an interface to the storage engine
15360 to acquire additional information about
15361 the original table.
15362 @param[in,out] create_info A blob with CREATE/ALTER TABLE
15363 parameters
15364 @param[in,out] alter_info Another blob with ALTER/CREATE parameters.
15365 Originally create_info was used only in
15366 CREATE TABLE and alter_info only in ALTER TABLE.
15367 But since ALTER might end-up doing CREATE,
15368 this distinction is gone and we just carry
15369 around two structures.
15370 @param[in,out] alter_ctx Runtime context for ALTER TABLE.
15371
15372 @return
15373 Fills various create_info members based on information retrieved
15374 from the storage engine.
15375 Sets create_info->varchar if the table has a VARCHAR column.
15376 Prepares alter_info->create_list and alter_info->key_list with
15377 columns and keys of the new table.
15378 @retval true error, out of memory or a semantical error in ALTER
15379 TABLE instructions
15380 @retval false success
15381 */
15382
15383 90926 bool mysql_prepare_alter_table(THD *thd, const dd::Table *src_table,
15384 TABLE *table, HA_CREATE_INFO *create_info,
15385 Alter_info *alter_info,
15386 Alter_table_ctx *alter_ctx) {
15387 90926 uint db_create_options =
15388 90926 (table->s->db_create_options & ~(HA_OPTION_PACK_RECORD));
15389 90926 uint64_t used_fields = create_info->used_fields;
15390
15391
1/2
✓ Branch 0 taken 90926 times.
✗ Branch 1 not taken.
90926 DBUG_TRACE;
15392
15393 // Prepare data in HA_CREATE_INFO shared by ALTER and upgrade code.
15394
1/2
✓ Branch 0 taken 90926 times.
✗ Branch 1 not taken.
90926 create_info->init_create_options_from_share(table->s, used_fields);
15395
15396
4/4
✓ Branch 0 taken 90680 times.
✓ Branch 1 taken 246 times.
✓ Branch 2 taken 5691 times.
✓ Branch 3 taken 84989 times.
90926 if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field) {
15397 /* Table has an autoincrement, copy value to new table */
15398
1/2
✓ Branch 0 taken 5691 times.
✗ Branch 1 not taken.
5691 table->file->info(HA_STATUS_AUTO);
15399 5691 create_info->auto_increment_value = table->file->stats.auto_increment_value;
15400 }
15401
15402 // Encryption was changed to not KEYRING and ALTER does not contain
15403 // encryption_key_id mark encryption_key_id as not set then
15404
2/2
✓ Branch 0 taken 4655 times.
✓ Branch 1 taken 86271 times.
90926 if (used_fields & HA_CREATE_USED_ENCRYPT &&
15405
2/2
✓ Branch 0 taken 4653 times.
✓ Branch 1 taken 2 times.
4655 0 != strncmp(create_info->encrypt_type.str, "KEYRING",
15406 4653 create_info->encrypt_type.length) &&
15407
1/2
✓ Branch 0 taken 4653 times.
✗ Branch 1 not taken.
4653 !(used_fields & HA_CREATE_USED_ENCRYPTION_KEY_ID)) {
15408 4653 create_info->used_fields &= ~(HA_CREATE_USED_ENCRYPTION_KEY_ID);
15409 4653 create_info->was_encryption_key_id_set = false;
15410 }
15411
15412
3/4
✓ Branch 0 taken 90926 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1203 times.
✓ Branch 3 taken 89723 times.
90926 if (prepare_fields_and_keys(thd, src_table, table, create_info, alter_info,
15413 alter_ctx, used_fields))
15414 1203 return true;
15415
15416
1/2
✓ Branch 0 taken 89723 times.
✗ Branch 1 not taken.
89723 table->file->update_create_info(create_info);
15417
15418 /* Get the autoextend_size value for the old table if the user did not
15419 specify it on the command line */
15420
7/8
✓ Branch 0 taken 88478 times.
✓ Branch 1 taken 1245 times.
✓ Branch 2 taken 88478 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 68013 times.
✓ Branch 5 taken 20465 times.
✓ Branch 6 taken 68013 times.
✓ Branch 7 taken 21710 times.
89723 if (src_table && src_table->engine() == "InnoDB") {
15421 68013 ulonglong autoextend_size{};
15422
15423
1/2
✓ Branch 0 taken 68013 times.
✗ Branch 1 not taken.
68013 dd::get_implicit_tablespace_options(thd, src_table, &autoextend_size);
15424
15425
2/2
✓ Branch 0 taken 62979 times.
✓ Branch 1 taken 5034 times.
68013 if (!create_info->m_implicit_tablespace_autoextend_size_change) {
15426 62979 create_info->m_implicit_tablespace_autoextend_size = autoextend_size;
15427 }
15428 }
15429
15430 /*
15431 NDB storage engine misuses handler::update_create_info() to implement
15432 special handling of table comments which are used to specify and store
15433 some NDB-specific table options. In the process it might report error.
15434 In order to detect and correctly handle such situation we need to call
15435 THD::is_error().
15436 */
15437
2/4
✓ Branch 0 taken 89723 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 89723 times.
89723 if (thd->is_error()) return true;
15438
15439
2/2
✓ Branch 0 taken 89706 times.
✓ Branch 1 taken 17 times.
89723 if ((create_info->table_options &
15440 89706 (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
15441
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 89704 times.
89706 (used_fields & HA_CREATE_USED_PACK_KEYS))
15442 19 db_create_options &= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
15443
2/2
✓ Branch 0 taken 85688 times.
✓ Branch 1 taken 4035 times.
89723 if ((create_info->table_options &
15444 85688 (HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT)) ||
15445
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 85683 times.
85688 (used_fields & HA_CREATE_USED_STATS_PERSISTENT))
15446 4040 db_create_options &=
15447 ~(HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT);
15448
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 89706 times.
89723 if (create_info->table_options & (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
15449 17 db_create_options &= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
15450
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 89717 times.
89723 if (create_info->table_options &
15451 (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
15452 6 db_create_options &=
15453 ~(HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE);
15454 89723 create_info->table_options |= db_create_options;
15455
15456
2/2
✓ Branch 0 taken 1245 times.
✓ Branch 1 taken 88478 times.
89723 if (table->s->tmp_table) create_info->options |= HA_LEX_CREATE_TMP_TABLE;
15457
15458 89723 return false;
15459 90926 }
15460
15461 /**
15462 Get Create_field object for newly created table by its name
15463 in the old version of table.
15464
15465 @param alter_info Alter_info describing newly created table.
15466 @param old_name Name of field in old table.
15467
15468 @returns Pointer to Create_field object, NULL - if field is
15469 not present in new version of table.
15470 */
15471
15472 67 static const Create_field *get_field_by_old_name(Alter_info *alter_info,
15473 const char *old_name) {
15474
1/2
✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
67 List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
15475 const Create_field *new_field;
15476
15477
1/2
✓ Branch 0 taken 145 times.
✗ Branch 1 not taken.
145 while ((new_field = new_field_it++)) {
15478
3/4
✓ Branch 0 taken 145 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 67 times.
✓ Branch 3 taken 78 times.
290 if (new_field->field &&
15479
3/4
✓ Branch 0 taken 145 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 67 times.
✓ Branch 3 taken 78 times.
145 (my_strcasecmp(system_charset_info, new_field->field->field_name,
15480 old_name) == 0))
15481 67 break;
15482 }
15483 67 return new_field;
15484 }
15485
15486 /** Type of change to foreign key column, */
15487
15488 enum class fk_column_change_type {
15489 NO_CHANGE,
15490 DATA_CHANGE,
15491 RENAMED,
15492 DROPPED,
15493 SAFE_FOR_PARENT
15494 };
15495
15496 /**
15497 Check that ALTER TABLE's changes on columns of a foreign key are allowed.
15498
15499 @tparam F Function class which returns foreign key's
15500 referenced or referencing (depending on
15501 whether we check ALTER TABLE that changes
15502 parent or child table) column name by its
15503 index.
15504
15505 @param[in] thd Thread context.
15506 @param[in] alter_info Alter_info describing changes to be done
15507 by ALTER TABLE.
15508 @param[in] fk_col_count Number of columns in the foreign key.
15509 @param[in] fk_columns Object of F type bound to the specific foreign
15510 key for which check is carried out.
15511 @param[out] bad_column_name Name of field on which ALTER TABLE tries to
15512 do prohibited operation.
15513
15514 @note This function takes into account value of @@foreign_key_checks
15515 setting.
15516
15517 @retval NO_CHANGE No significant changes are to be done on
15518 foreign key columns.
15519 @retval DATA_CHANGE ALTER TABLE might result in value
15520 change in foreign key column (and
15521 foreign_key_checks is on).
15522 @retval ENAMED Foreign key column is renamed.
15523 @retval DROPPED Foreign key column is dropped.
15524 @retval SAFE_FOR_PARENT The column change is safe if this is a
15525 referenced column.
15526 */
15527
15528 template <class F>
15529 126 static fk_column_change_type fk_check_column_changes(
15530 THD *thd, Alter_info *alter_info, uint fk_col_count, const F &fk_columns,
15531 const char **bad_column_name) {
15532 126 *bad_column_name = nullptr;
15533
15534
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 60 times.
254 for (uint i = 0; i < fk_col_count; ++i) {
15535 134 const char *column = fk_columns(i);
15536 134 const Create_field *new_field = get_field_by_old_name(alter_info, column);
15537
15538
1/2
✓ Branch 0 taken 67 times.
✗ Branch 1 not taken.
134 if (new_field) {
15539 134 Field *old_field = new_field->field;
15540
15541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
134 if (my_strcasecmp(system_charset_info, old_field->field_name,
15542 new_field->field_name)) {
15543 /*
15544 Copy algorithm doesn't support proper renaming of columns in
15545 the foreign key yet. At the moment we lack API which will tell
15546 SE that foreign keys should be updated to use new name of column
15547 like it happens in case of in-place algorithm.
15548 */
15549 *bad_column_name = column;
15550 return fk_column_change_type::RENAMED;
15551 }
15552
15553 134 const auto fields_differ =
15554 134 (old_field->is_equal(new_field) == IS_EQUAL_NO);
15555
15556
6/6
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 36 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 62 times.
190 if (fields_differ || ((new_field->flags & NOT_NULL_FLAG) &&
15557
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 26 times.
56 !old_field->is_flag_set(NOT_NULL_FLAG))) {
15558
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
10 if (!(thd->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS)) {
15559 /*
15560 Column in a FK has changed significantly. Unless
15561 foreign_key_checks are off we prohibit this since this
15562 means values in this column might be changed by ALTER
15563 and thus referential integrity might be broken,
15564 */
15565 6 *bad_column_name = column;
15566 /* NULL to NOT NULL column change is safe for referenced columns */
15567
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
6 return fields_differ ? fk_column_change_type::DATA_CHANGE
15568 6 : fk_column_change_type::SAFE_FOR_PARENT;
15569 }
15570 }
15571
2/4
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
128 assert(old_field->is_gcol() == new_field->is_gcol() &&
15572 old_field->is_virtual_gcol() == new_field->is_virtual_gcol());
15573
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
128 assert(!old_field->is_gcol() || old_field->gcol_expr_is_equal(new_field));
15574 } else {
15575 /*
15576 Column in FK was dropped. Most likely this will break
15577 integrity constraints of InnoDB data-dictionary (and thus
15578 InnoDB will emit an error), so we prohibit this right away
15579 even if foreign_key_checks are off.
15580 This also includes a rare case when another field replaces
15581 field being dropped since it is easy to break referential
15582 integrity in this case.
15583 */
15584 *bad_column_name = column;
15585 return fk_column_change_type::DROPPED;
15586 }
15587 }
15588
15589 120 return fk_column_change_type::NO_CHANGE;
15590 }
15591
15592 /**
15593 Check if ALTER TABLE we are about to execute using COPY algorithm
15594 is not supported as it might break referential integrity.
15595
15596 @note If foreign_key_checks is disabled (=0), we allow to break
15597 referential integrity. But we still disallow some operations
15598 like dropping or renaming columns in foreign key since they
15599 are likely to break consistency of InnoDB data-dictionary
15600 and thus will end-up in error anyway.
15601
15602 @param[in] thd Thread context.
15603 @param[in] table_list TABLE_LIST element for the table to be altered.
15604 @param[in] table_def dd::Table for old version of table to be altered.
15605 @param[in] alter_info Lists of fields, keys to be changed, added
15606 or dropped.
15607
15608 @retval false Success.
15609 @retval true Error, ALTER - tries to do change which is not compatible
15610 with foreign key definitions on the table.
15611 */
15612
15613 20744 static bool fk_check_copy_alter_table(THD *thd, TABLE_LIST *table_list,
15614 const dd::Table *table_def,
15615 Alter_info *alter_info) {
15616
1/2
✓ Branch 0 taken 20744 times.
✗ Branch 1 not taken.
20744 DBUG_TRACE;
15617
15618
2/2
✓ Branch 0 taken 1151 times.
✓ Branch 1 taken 19593 times.
20744 if (!table_def) return false; // Must be a temporary table.
15619
15620
3/4
✓ Branch 0 taken 19593 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 19593 times.
19599 for (const dd::Foreign_key_parent *fk_p : table_def->foreign_key_parents()) {
15621 /*
15622 First, check foreign keys in which table participates as parent.
15623 To get necessary information about such a foreign key we need to
15624 acquire dd::Table object describing child table.
15625 */
15626
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
15627 const dd::Table *child_table_def;
15628
15629 bool self_ref_fk =
15630
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 (my_strcasecmp(table_alias_charset, fk_p->child_schema_name().c_str(),
15631
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
12 table_list->db) == 0 &&
15632
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5 times.
6 my_strcasecmp(table_alias_charset, fk_p->child_table_name().c_str(),
15633 6 table_list->table_name) == 0);
15634
15635
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (self_ref_fk)
15636 1 child_table_def = table_def;
15637 else {
15638
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (thd->dd_client()->acquire(fk_p->child_schema_name(),
15639 fk_p->child_table_name(), &child_table_def))
15640 return true;
15641 }
15642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 assert(child_table_def != nullptr);
15643
15644
6/10
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 10 times.
✓ Branch 9 taken 6 times.
16 for (const dd::Foreign_key *fk : child_table_def->foreign_keys()) {
15645 /*
15646 Skip all foreign keys except one which corresponds to the
15647 dd::Foreign_key_parent object being processed.
15648 */
15649
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 if (my_strcasecmp(system_charset_info, fk_p->fk_name().c_str(),
15650
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
10 fk->name().c_str()) != 0)
15651 4 continue;
15652
15653
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (self_ref_fk) {
15654 /*
15655 Also skip all foreign keys which are to be dropped by this
15656 ALTER TABLE. This is possible when a foreign key has the
15657 same table as child and parent.
15658 */
15659 1 bool is_dropped = false;
15660
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 for (const Alter_drop *drop : alter_info->drop_list) {
15661 /* Names of foreign keys in InnoDB are case-insensitive. */
15662 if ((drop->type == Alter_drop::FOREIGN_KEY) &&
15663 (my_strcasecmp(system_charset_info, fk->name().c_str(),
15664 drop->name) == 0)) {
15665 is_dropped = true;
15666 break;
15667 }
15668 }
15669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (is_dropped) continue;
15670 }
15671
15672 enum fk_column_change_type changes;
15673 const char *bad_column_name;
15674
15675 6 auto fk_columns_lambda = [fk](uint i) {
15676 6 return fk->elements()[i]->referenced_column_name().c_str();
15677 6 };
15678
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 changes = fk_check_column_changes(thd, alter_info, fk->elements().size(),
15679 fk_columns_lambda, &bad_column_name);
15680
15681
1/5
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 switch (changes) {
15682 6 case fk_column_change_type::SAFE_FOR_PARENT:
15683 case fk_column_change_type::NO_CHANGE:
15684 /* No significant changes. We can proceed with ALTER! */
15685 6 break;
15686 case fk_column_change_type::DATA_CHANGE: {
15687 char buff[NAME_LEN * 2 + 2];
15688 strxnmov(buff, sizeof(buff) - 1, fk_p->child_schema_name().c_str(),
15689 ".", fk_p->child_table_name().c_str(), NullS);
15690 my_error(ER_FK_COLUMN_CANNOT_CHANGE_CHILD, MYF(0), bad_column_name,
15691 fk->name().c_str(), buff);
15692 return true;
15693 }
15694 case fk_column_change_type::RENAMED:
15695 my_error(
15696 ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0), "ALGORITHM=COPY",
15697 ER_THD(thd, ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME),
15698 "ALGORITHM=INPLACE");
15699 return true;
15700 case fk_column_change_type::DROPPED:
15701 /*
15702 Should already have been checked in
15703 transfer_preexisting_foreign_keys().
15704 */
15705 assert(false);
15706 default:
15707 assert(0);
15708 }
15709 }
15710
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 }
15711
15712
6/10
✓ Branch 0 taken 19593 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19593 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19593 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 78 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 78 times.
✓ Branch 9 taken 19591 times.
19669 for (const dd::Foreign_key *fk : table_def->foreign_keys()) {
15713 /*
15714 Now, check foreign keys in which table participates as child.
15715
15716 Skip all foreign keys which are to be dropped by this ALTER TABLE.
15717 */
15718 78 bool is_dropped = false;
15719
3/4
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 57 times.
169 for (const Alter_drop *drop : alter_info->drop_list) {
15720 /* Names of foreign keys in InnoDB are case-insensitive. */
15721
4/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 91 times.
136 if ((drop->type == Alter_drop::FOREIGN_KEY) &&
15722
4/6
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21 times.
✓ Branch 5 taken 3 times.
24 (my_strcasecmp(system_charset_info, fk->name().c_str(), drop->name) ==
15723 0)) {
15724 21 is_dropped = true;
15725 21 break;
15726 }
15727 }
15728
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 57 times.
78 if (is_dropped) continue;
15729
15730 enum fk_column_change_type changes;
15731 const char *bad_column_name;
15732
15733 61 auto fk_columns_lambda = [fk](uint i) {
15734 61 return fk->elements()[i]->column().name().c_str();
15735 57 };
15736
2/4
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
57 changes = fk_check_column_changes(thd, alter_info, fk->elements().size(),
15737 fk_columns_lambda, &bad_column_name);
15738
15739
2/5
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
57 switch (changes) {
15740 55 case fk_column_change_type::NO_CHANGE:
15741 /* No significant changes. We can proceed with ALTER! */
15742 55 break;
15743 2 case fk_column_change_type::SAFE_FOR_PARENT:
15744 case fk_column_change_type::DATA_CHANGE:
15745
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_FK_COLUMN_CANNOT_CHANGE, MYF(0), bad_column_name,
15746
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 fk->name().c_str());
15747 2 return true;
15748 case fk_column_change_type::RENAMED:
15749 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
15750 "ALGORITHM=COPY",
15751 ER_THD(thd, ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME),
15752 "ALGORITHM=INPLACE");
15753 return true;
15754 case fk_column_change_type::DROPPED:
15755 /*
15756 Should already have been checked in
15757 transfer_preexisting_foreign_keys().
15758 */
15759 assert(false);
15760 }
15761 }
15762
15763 19591 return false;
15764 20744 }
15765
15766 1832 bool collect_and_lock_fk_tables_for_rename_table(
15767 THD *thd, const char *db, const char *table_name,
15768 const dd::Table *table_def, const char *new_db, const char *new_table_name,
15769 handlerton *hton, Foreign_key_parents_invalidator *fk_invalidator) {
15770
1/2
✓ Branch 0 taken 1832 times.
✗ Branch 1 not taken.
1832 MDL_request_list mdl_requests;
15771
15772
1/2
✓ Branch 0 taken 1832 times.
✗ Branch 1 not taken.
1832 if (collect_fk_children(thd, db, table_name, hton, MDL_EXCLUSIVE,
15773 1832 &mdl_requests) ||
15774
2/4
✓ Branch 0 taken 1832 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1832 times.
✗ Branch 3 not taken.
1832 collect_fk_children(thd, new_db, new_table_name, hton, MDL_EXCLUSIVE,
15775 1832 &mdl_requests) ||
15776
2/4
✓ Branch 0 taken 1832 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1832 times.
✗ Branch 3 not taken.
1832 collect_fk_parents_for_all_fks(thd, table_def, hton, MDL_EXCLUSIVE,
15777
2/4
✓ Branch 0 taken 1832 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1832 times.
3664 &mdl_requests, fk_invalidator) ||
15778
2/4
✓ Branch 0 taken 1832 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1832 times.
1832 collect_fk_names_for_rename_table(thd, db, table_name, table_def, hton,
15779 new_db, new_table_name, &mdl_requests))
15780 return true;
15781
15782
3/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 1796 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1832 times.
1868 if (!mdl_requests.is_empty() &&
15783
2/4
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 36 times.
36 thd->mdl_context.acquire_locks(&mdl_requests,
15784 thd->variables.lock_wait_timeout))
15785 return true;
15786
15787 1832 return false;
15788 }
15789
15790 1832 bool adjust_adopted_self_ref_fk_for_simple_rename_table(
15791 THD *thd, const char *db, const char *table_name, const char *new_db,
15792 const char *new_table_name, handlerton *hton) {
15793
1/2
✓ Branch 0 taken 1832 times.
✗ Branch 1 not taken.
1832 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
15794 1832 dd::Table *table_def = nullptr;
15795
15796
4/8
✓ Branch 0 taken 1832 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1832 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1832 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1832 times.
1832 if (thd->dd_client()->acquire_for_modification(db, table_name, &table_def))
15797 return true;
15798
15799
3/4
✓ Branch 0 taken 1832 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1813 times.
✓ Branch 3 taken 19 times.
1832 if (table_def->foreign_keys()->empty()) return false;
15800
15801 19 bool has_adopted_fk = false;
15802
6/10
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 26 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 26 times.
✓ Branch 9 taken 19 times.
45 for (dd::Foreign_key *fk : *(table_def->foreign_keys())) {
15803
2/4
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
26 if (my_strcasecmp(table_alias_charset,
15804 fk->referenced_table_schema_name().c_str(),
15805
3/4
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 24 times.
52 new_db) == 0 &&
15806
4/6
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 24 times.
26 my_strcasecmp(table_alias_charset, fk->referenced_table_name().c_str(),
15807 new_table_name) == 0) {
15808 /*
15809 Check that table has a column which is compatible with the foreign key's
15810 referenced column.
15811 */
15812
6/10
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 2 times.
4 for (dd::Foreign_key_element *fk_el : *(fk->elements())) {
15813
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (check_table_has_col_compatible_with_fk_ref_col(table_def, fk, fk_el,
15814 hton))
15815 return true;
15816 }
15817
15818
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (prepare_fk_parent_key(hton, table_def, nullptr, nullptr, true, fk))
15819 return true;
15820
15821 2 has_adopted_fk = true;
15822 }
15823 }
15824
15825
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
19 return (has_adopted_fk && thd->dd_client()->update(table_def));
15826 1832 }
15827
15828 1771 bool adjust_fks_for_rename_table(THD *thd, const char *db,
15829 const char *table_name, const char *new_db,
15830 const char *new_table_name, handlerton *hton) {
15831 1771 const dd::Table *new_table = nullptr;
15832
15833
4/8
✓ Branch 0 taken 1771 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1771 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1771 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1771 times.
1771 if (thd->dd_client()->acquire(new_db, new_table_name, &new_table))
15834 return true;
15835
15836
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1771 times.
1771 assert(new_table != nullptr);
15837
15838
2/4
✓ Branch 0 taken 1771 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1771 times.
1771 if (adjust_fk_children_after_parent_rename(thd, db, table_name, hton, new_db,
15839 new_table_name))
15840 return true;
15841
15842
3/4
✓ Branch 0 taken 1771 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1767 times.
1771 if (adjust_fk_children_after_parent_def_change(thd, new_db, new_table_name,
15843 hton, new_table, nullptr))
15844 4 return true;
15845
15846
2/4
✓ Branch 0 taken 1767 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1767 times.
1767 if (adjust_fk_parents(thd, new_db, new_table_name, true, nullptr))
15847 return true;
15848
15849 1767 return false;
15850 }
15851
15852 /**
15853 Check if ALTER TABLE in question is a simple ALTER TABLE RENAME or
15854 ALTER TABLE ENABLE/DISABLE KEYS.
15855
15856 @param alter_info Alter_info describing ALTER.
15857 */
15858 182267 static bool is_simple_rename_or_index_change(const Alter_info *alter_info) {
15859 182267 return (!(alter_info->flags &
15860
2/2
✓ Branch 0 taken 4139 times.
✓ Branch 1 taken 178128 times.
186406 ~(Alter_info::ALTER_RENAME | Alter_info::ALTER_KEYS_ONOFF)) &&
15861
2/2
✓ Branch 0 taken 4103 times.
✓ Branch 1 taken 36 times.
4139 alter_info->requested_algorithm !=
15862 182267 Alter_info::ALTER_TABLE_ALGORITHM_COPY);
15863 }
15864
15865 /**
15866 Rename table and/or turn indexes on/off without touching .FRM
15867
15868 @param thd Thread handler
15869 @param new_schema Target schema.
15870 @param table_list TABLE_LIST for the table to change
15871 @param keys_onoff ENABLE or DISABLE KEYS?
15872 @param alter_ctx ALTER TABLE runtime context.
15873
15874 @return Operation status
15875 @retval false Success
15876 @retval true Failure
15877 */
15878 2033 static bool simple_rename_or_index_change(
15879 THD *thd, const dd::Schema &new_schema, TABLE_LIST *table_list,
15880 Alter_info::enum_enable_or_disable keys_onoff, Alter_table_ctx *alter_ctx) {
15881 2033 TABLE *table = table_list->table;
15882 2033 MDL_ticket *mdl_ticket = table->mdl_ticket;
15883 2033 int error = 0;
15884
1/2
✓ Branch 0 taken 2033 times.
✗ Branch 1 not taken.
2033 handlerton *old_db_type = table->s->db_type();
15885 2033 bool atomic_ddl = (old_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL);
15886 2033 Foreign_key_parents_invalidator fk_invalidator;
15887
15888
1/2
✓ Branch 0 taken 2033 times.
✗ Branch 1 not taken.
2033 DBUG_TRACE;
15889
15890
2/2
✓ Branch 0 taken 1229 times.
✓ Branch 1 taken 804 times.
2033 if (keys_onoff != Alter_info::LEAVE_AS_IS) {
15891
3/4
✓ Branch 0 taken 1229 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1225 times.
1229 if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
15892 4 return true;
15893
15894 // It's now safe to take the table level lock.
15895
2/4
✓ Branch 0 taken 1225 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1225 times.
1225 if (lock_tables(thd, table_list, alter_ctx->tables_opened, 0)) return true;
15896
15897
2/2
✓ Branch 0 taken 618 times.
✓ Branch 1 taken 607 times.
1225 if (keys_onoff == Alter_info::ENABLE) {
15898
2/4
✓ Branch 0 taken 618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 618 times.
✗ Branch 3 not taken.
618 DEBUG_SYNC(thd, "alter_table_enable_indexes");
15899
2/6
✓ Branch 0 taken 618 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 618 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
618 DBUG_EXECUTE_IF("sleep_alter_enable_indexes", my_sleep(6000000););
15900
1/2
✓ Branch 0 taken 618 times.
✗ Branch 1 not taken.
618 error = table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
15901
1/2
✓ Branch 0 taken 607 times.
✗ Branch 1 not taken.
607 } else if (keys_onoff == Alter_info::DISABLE)
15902
1/2
✓ Branch 0 taken 607 times.
✗ Branch 1 not taken.
607 error = table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
15903
15904
2/2
✓ Branch 0 taken 1128 times.
✓ Branch 1 taken 97 times.
1225 if (error == HA_ERR_WRONG_COMMAND) {
15905
2/4
✓ Branch 0 taken 1128 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1128 times.
✗ Branch 3 not taken.
1128 push_warning_printf(thd, Sql_condition::SL_NOTE, ER_ILLEGAL_HA,
15906 ER_THD(thd, ER_ILLEGAL_HA), table->alias);
15907 1128 error = 0;
15908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
97 } else if (error > 0) {
15909 table->file->print_error(error, MYF(0));
15910 error = -1;
15911 } else {
15912 /**
15913 Update mysql.tables.options with keys_disabled=1/0 based on keys_onoff.
15914 This will used by INFORMATION_SCHEMA.STATISTICS system view to display
15915 keys were disabled.
15916 */
15917 97 dd::Table *tab_obj = nullptr;
15918
15919
4/8
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 97 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 97 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 97 times.
97 if (thd->dd_client()->acquire_for_modification(
15920 table_list->db, table_list->table_name, &tab_obj))
15921 error = -1;
15922 else {
15923
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
97 assert(tab_obj != nullptr);
15924
15925
5/8
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 50 times.
✓ Branch 4 taken 97 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 97 times.
✗ Branch 7 not taken.
97 tab_obj->options().set("keys_disabled",
15926 (keys_onoff == Alter_info::DISABLE ? 1 : 0));
15927
15928 // Update the changes
15929
1/2
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
97 bool result = thd->dd_client()->update(tab_obj);
15930
2/4
✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 97 times.
✗ Branch 3 not taken.
97 if (!atomic_ddl) result = trans_intermediate_ddl_commit(thd, result);
15931
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
97 if (result) error = -1;
15932 }
15933 }
15934 }
15935
15936
5/6
✓ Branch 0 taken 2029 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 771 times.
✓ Branch 3 taken 1258 times.
✓ Branch 4 taken 771 times.
✓ Branch 5 taken 1258 times.
2029 if (!error && alter_ctx->is_table_renamed()) {
15937
1/2
✓ Branch 0 taken 771 times.
✗ Branch 1 not taken.
771 THD_STAGE_INFO(thd, stage_rename);
15938 /*
15939 Then do a 'simple' rename of the table. First we need to close all
15940 instances of 'source' table.
15941 Note that if wait_while_table_is_used() returns error here (i.e. if
15942 this thread was killed) then it must be that previous step of
15943 simple rename did nothing and therefore we can safely return
15944 without additional clean-up.
15945 */
15946
3/4
✓ Branch 0 taken 771 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 766 times.
771 if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
15947 21 return true;
15948
15949 766 const dd::Table *table_def = nullptr;
15950
4/8
✓ Branch 0 taken 766 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 766 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 766 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 766 times.
766 if (thd->dd_client()->acquire(table_list->db, table_list->table_name,
15951 &table_def))
15952 return true;
15953
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 766 times.
766 assert(table_def != nullptr);
15954
15955 /*
15956 Check table encryption privilege, if rename changes database.
15957 */
15958
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 627 times.
766 if (alter_ctx->is_database_changed()) {
15959 139 bool is_general_tablespace{false};
15960 139 bool is_table_encrypted{false};
15961 dd::Encrypt_result result =
15962
1/2
✓ Branch 0 taken 139 times.
✗ Branch 1 not taken.
139 dd::is_tablespace_encrypted(thd, *table_def, &is_general_tablespace);
15963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if (result.error) {
15964 16 return true;
15965 }
15966 139 is_table_encrypted = result.value;
15967 // If implicit tablespace, read the encryption clause value.
15968
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 32 times.
246 if (!is_general_tablespace &&
15969
9/14
✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 107 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 106 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 107 times.
✓ Branch 9 taken 32 times.
✓ Branch 10 taken 106 times.
✓ Branch 11 taken 33 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
246 table_def->options().exists("encrypt_type")) {
15970 106 dd::String_type et;
15971
3/6
✓ Branch 0 taken 106 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 106 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 106 times.
✗ Branch 5 not taken.
106 (void)table_def->options().get("encrypt_type", &et);
15972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 106 times.
106 assert(et.empty() == false);
15973
1/2
✓ Branch 0 taken 106 times.
✗ Branch 1 not taken.
106 is_table_encrypted = is_encrypted(et);
15974 106 }
15975
15976 // If table encryption differ from schema encryption, check privilege.
15977
3/4
✓ Branch 0 taken 139 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 75 times.
139 if (new_schema.default_encryption() != is_table_encrypted) {
15978
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 16 times.
64 if (opt_table_encryption_privilege_check) {
15979
3/4
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 32 times.
48 if (check_table_encryption_admin_access(thd)) {
15980
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 my_error(ER_CANNOT_SET_TABLE_ENCRYPTION, MYF(0));
15981 16 return true;
15982 }
15983
6/8
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 8 times.
16 } else if (new_schema.default_encryption() && !is_table_encrypted) {
15984
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 push_warning(thd, Sql_condition::SL_WARNING,
15985 WARN_UNENCRYPTED_TABLE_IN_ENCRYPTED_DB,
15986 ER_THD(thd, WARN_UNENCRYPTED_TABLE_IN_ENCRYPTED_DB));
15987 }
15988 }
15989 }
15990
15991
3/4
✓ Branch 0 taken 723 times.
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 750 times.
1473 if ((old_db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS) &&
15992
2/4
✓ Branch 0 taken 723 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 723 times.
723 collect_and_lock_fk_tables_for_rename_table(
15993 thd, table_list->db, table_list->table_name, table_def,
15994 alter_ctx->new_db, alter_ctx->new_alias, old_db_type,
15995 &fk_invalidator)) {
15996 return true;
15997 }
15998
15999
2/4
✓ Branch 0 taken 750 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 750 times.
750 if (lock_check_constraint_names_for_rename(
16000 thd, table_list->db, table_list->table_name, table_def,
16001 alter_ctx->new_db, alter_ctx->new_alias))
16002 return true;
16003
16004
1/2
✓ Branch 0 taken 750 times.
✗ Branch 1 not taken.
750 close_all_tables_for_name(thd, table->s, false, nullptr);
16005
16006 /*
16007 Orphan non-self-referencing foreign keys may become non-orphan/adopted
16008 self-referencing foreign keys. Check that table has compatible referenced
16009 column and parent key for such foreign key. Also, update
16010 DD.UNIQUE_CONSTRAINT_NAME.
16011 */
16012
3/4
✓ Branch 0 taken 723 times.
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 750 times.
1473 if ((old_db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS) &&
16013
2/4
✓ Branch 0 taken 723 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 723 times.
723 adjust_adopted_self_ref_fk_for_simple_rename_table(
16014 thd, table_list->db, table_list->table_name, alter_ctx->new_db,
16015 alter_ctx->new_alias, old_db_type))
16016 error = -1;
16017
16018
1/2
✓ Branch 0 taken 750 times.
✗ Branch 1 not taken.
750 if (!error) {
16019
5/6
✓ Branch 0 taken 723 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 750 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 740 times.
750 if (mysql_rename_table(thd, old_db_type, alter_ctx->db,
16020 alter_ctx->table_name, alter_ctx->db,
16021 alter_ctx->table_name, new_schema,
16022 alter_ctx->new_db, alter_ctx->new_alias,
16023 (atomic_ddl ? NO_DD_COMMIT : 0)))
16024 10 error = -1;
16025
2/2
✓ Branch 0 taken 713 times.
✓ Branch 1 taken 27 times.
740 else if (old_db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS) {
16026 /*
16027 We don't have SEs which support FKs and don't support atomic DDL.
16028 If we ever to support such engines we need to decide how to handle
16029 errors in the below code for them.
16030 */
16031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 713 times.
713 assert(atomic_ddl);
16032
16033
3/4
✓ Branch 0 taken 713 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 712 times.
713 if (adjust_fks_for_rename_table(
16034 thd, table_list->db, table_list->table_name, alter_ctx->new_db,
16035 alter_ctx->new_alias, old_db_type))
16036 1 error = -1;
16037 }
16038 }
16039 }
16040
16041
2/2
✓ Branch 0 taken 1997 times.
✓ Branch 1 taken 11 times.
2008 if (!error) {
16042 error =
16043
3/6
✓ Branch 0 taken 1997 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1997 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1997 times.
✗ Branch 5 not taken.
1997 write_bin_log(thd, true, thd->query().str, thd->query().length,
16044
6/6
✓ Branch 0 taken 1795 times.
✓ Branch 1 taken 202 times.
✓ Branch 2 taken 745 times.
✓ Branch 3 taken 1050 times.
✓ Branch 4 taken 712 times.
✓ Branch 5 taken 33 times.
2742 atomic_ddl && (keys_onoff != Alter_info::LEAVE_AS_IS ||
16045 745 alter_ctx->is_table_renamed()));
16046
16047 // Update referencing views metadata.
16048
2/2
✓ Branch 0 taken 1995 times.
✓ Branch 1 taken 2 times.
1997 if (!error) {
16049
1/2
✓ Branch 0 taken 1995 times.
✗ Branch 1 not taken.
1995 Uncommitted_tables_guard uncommitted_tables(thd);
16050
16051 3990 error = update_referencing_views_metadata(
16052
1/2
✓ Branch 0 taken 1995 times.
✗ Branch 1 not taken.
1995 thd, table_list, alter_ctx->new_db, alter_ctx->new_alias, !atomic_ddl,
16053 &uncommitted_tables);
16054
16055
2/2
✓ Branch 0 taken 737 times.
✓ Branch 1 taken 1258 times.
1995 if (alter_ctx->is_table_renamed()) {
16056
1/2
✓ Branch 0 taken 737 times.
✗ Branch 1 not taken.
737 uncommitted_tables.add_table(table_list);
16057
1/2
✓ Branch 0 taken 737 times.
✗ Branch 1 not taken.
737 tdc_remove_table(thd, TDC_RT_REMOVE_ALL, alter_ctx->new_db,
16058 alter_ctx->new_name, false);
16059 }
16060 1995 }
16061
16062 /*
16063 Commit changes to data-dictionary, SE and binary log if it was not done
16064 earlier. We need to do this before releasing/downgrading MDL.
16065 */
16066
4/4
✓ Branch 0 taken 1995 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1794 times.
✓ Branch 3 taken 201 times.
1997 if (!error && atomic_ddl)
16067
4/8
✓ Branch 0 taken 1794 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1794 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1785 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1785 times.
1794 error = (trans_commit_stmt(thd) || trans_commit_implicit(thd));
16068
16069
3/4
✓ Branch 0 taken 1986 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1986 times.
✗ Branch 3 not taken.
1988 if (!error) fk_invalidator.invalidate(thd);
16070 }
16071
16072
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1986 times.
1999 if (error) {
16073 /*
16074 We need rollback possible changes to data-dictionary before releasing
16075 or downgrading metadata lock.
16076
16077 Full rollback will synchronize state of data-dictionary in
16078 cache and on disk. Also it is needed in case we have
16079 THD::transaction_rollback_request.
16080 */
16081
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 trans_rollback_stmt(thd);
16082
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 trans_rollback(thd);
16083 }
16084
16085
4/6
✓ Branch 0 taken 1797 times.
✓ Branch 1 taken 202 times.
✓ Branch 2 taken 1797 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1797 times.
✗ Branch 5 not taken.
1999 if (atomic_ddl && old_db_type->post_ddl) old_db_type->post_ddl(thd);
16086
16087
2/2
✓ Branch 0 taken 1986 times.
✓ Branch 1 taken 13 times.
1999 if (!error) {
16088
2/2
✓ Branch 0 taken 728 times.
✓ Branch 1 taken 1258 times.
1986 if (alter_ctx->is_table_renamed())
16089
1/2
✓ Branch 0 taken 728 times.
✗ Branch 1 not taken.
728 thd->locked_tables_list.rename_locked_table(
16090 table_list, alter_ctx->new_db, alter_ctx->new_name,
16091 alter_ctx->target_mdl_request.ticket);
16092 } else {
16093
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
13 if (atomic_ddl) {
16094 /*
16095 Engines that support atomic DDL restore status-quo on error.
16096 So we can safely try to reopen table under old name.
16097 */
16098 } else {
16099 /*
16100 For engines which don't support atomic DDL we simply close
16101 the table and later downgrade/release metadata lock, as we
16102 don't track at which step error has occurred exactly.
16103
16104 Since such engines do not support FKs downgrading/releasing
16105 the metadata locks should not cause problems with violating
16106 FK invariants for LOCK TABLES. For the same reason, the below
16107 call won't unlink any parent tables which might have been
16108 closed by FK invalidator.
16109 */
16110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(!(old_db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS));
16111
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 thd->locked_tables_list.unlink_all_closed_tables(thd, nullptr, 0);
16112 }
16113 }
16114
16115
1/2
✓ Branch 0 taken 1999 times.
✗ Branch 1 not taken.
1999 bool reopen_error = thd->locked_tables_list.reopen_tables(thd);
16116
16117
4/6
✓ Branch 0 taken 1986 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 1986 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1986 times.
✗ Branch 5 not taken.
1999 if (!error && !reopen_error) my_ok(thd);
16118
16119
2/2
✓ Branch 0 taken 894 times.
✓ Branch 1 taken 1105 times.
1999 if ((thd->locked_tables_mode == LTM_LOCK_TABLES ||
16120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 894 times.
894 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) {
16121 /*
16122 Under LOCK TABLES we should adjust meta-data locks before finishing
16123 statement. Otherwise we can rely on them being released
16124 along with the implicit commit.
16125 */
16126
6/6
✓ Branch 0 taken 1103 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 1094 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 1096 times.
1105 if (!error && alter_ctx->is_table_renamed()) {
16127 /*
16128 Note that we ignore reopen_error value here as not keeping target
16129 metadata locks in this case can lead to breaking foreign key
16130 invariants for LOCK TABLES.
16131 */
16132
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 thd->mdl_context.release_all_locks_for_name(mdl_ticket);
16133
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 thd->mdl_context.set_lock_duration(alter_ctx->target_mdl_request.ticket,
16134 MDL_EXPLICIT);
16135
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 alter_ctx->target_mdl_request.ticket->downgrade_lock(
16136 MDL_SHARED_NO_READ_WRITE);
16137
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 if (alter_ctx->is_database_changed())
16138
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 thd->mdl_context.set_lock_duration(
16139 alter_ctx->target_db_mdl_request.ticket, MDL_EXPLICIT);
16140 } else
16141
1/2
✓ Branch 0 taken 1096 times.
✗ Branch 1 not taken.
1096 mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
16142 }
16143
3/4
✓ Branch 0 taken 1986 times.
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1986 times.
1999 return error != 0 || reopen_error;
16144 2024 }
16145
16146 /*
16147 Temporarily remove secondary keys previously stored in
16148 alter_info->delayed_key_info.
16149 */
16150 5 static bool remove_secondary_keys(
16151 THD *thd, HA_CREATE_INFO *create_info, TABLE *table, Alter_info *alter_info,
16152 const dd::Table *table_def, dd::Table *altered_table_def,
16153 std::vector<dd::Index *> *dd_disabled_sec_keys) {
16154 uint i;
16155
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 DBUG_TRACE;
16156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 assert(alter_info->delayed_key_count > 0);
16157
16158 /*
16159 We need to mark all fields for read and write as being done in
16160 mysql_alter_table.
16161 */
16162
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 table->use_all_columns();
16163
16164 /*
16165 Create Alter_info for the table and fill create_list with fields
16166 definitions. Note that fields not changed, so we set field==orig_field.
16167 */
16168
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 Alter_info alter_info_new(thd->mem_root);
16169 Field **f_ptr, *field;
16170
16171
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (f_ptr = table->field; (field = *f_ptr); f_ptr++) {
16172
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 Create_field *new_field = new (thd->mem_root) Create_field(field, field);
16173
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 alter_info_new.create_list.push_back(new_field);
16174 }
16175
16176 /* table->key_info cannot be passed to ha_alter_info constructor,
16177 because it has 1-based fieldnr in key_parts while ha_alter_info
16178 expect them to be 0-based */
16179
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 KEY *key_buf = (KEY *)thd->alloc(sizeof(KEY) * table->s->keys);
16180
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5 times.
13 for (uint key_idx = 0; key_idx < table->s->keys; key_idx++) {
16181 8 KEY *key = table->key_info + key_idx;
16182 16 KEY_PART_INFO *key_parts_buf = (KEY_PART_INFO *)thd->alloc(
16183
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 sizeof(KEY_PART_INFO) * key->user_defined_key_parts);
16184
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 for (uint key_part_idx = 0; key_part_idx < key->user_defined_key_parts;
16185 key_part_idx++) {
16186 8 key_parts_buf[key_part_idx] = key->key_part[key_part_idx];
16187 8 key_parts_buf[key_part_idx].fieldnr--;
16188 }
16189 8 key_buf[key_idx] = *key;
16190 8 key_buf[key_idx].key_part = key_parts_buf;
16191 }
16192
16193 Alter_inplace_info ha_alter_info(create_info, &alter_info_new, false, key_buf,
16194 5 table->s->keys, thd->work_part_info);
16195
16196 5 ha_alter_info.handler_flags = Alter_inplace_info::DROP_INDEX;
16197 5 ha_alter_info.index_drop_count = alter_info->delayed_key_count;
16198
16199 /* Fill index_drop_buffer with keys to drop */
16200 5 ha_alter_info.index_drop_buffer =
16201
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 (KEY **)thd->alloc(sizeof(KEY *) * alter_info->delayed_key_count);
16202
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 for (i = 0; i < alter_info->delayed_key_count; i++)
16203 7 ha_alter_info.index_drop_buffer[i] = &(alter_info->delayed_key_info[i]);
16204
16205
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (table->file->check_if_supported_inplace_alter(table, &ha_alter_info) ==
16206 HA_ALTER_INPLACE_NOT_SUPPORTED)
16207 return true;
16208
16209
6/10
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✓ Branch 9 taken 5 times.
17 for (const auto index : *altered_table_def->indexes()) {
16210
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 const char *dd_index_name = index->name().c_str();
16211
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
30 for (i = 0; i < alter_info->delayed_key_count; i++) {
16212
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 11 times.
18 if (strcmp(alter_info->delayed_key_info[i].name, dd_index_name) == 0) {
16213
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 dd_disabled_sec_keys->push_back(index);
16214
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 assert(index->type() == dd::Index::IT_MULTIPLE);
16215 7 index->set_disabled(true);
16216 }
16217 }
16218 }
16219
16220 /* Clone old Table and disable indexes we want to remove
16221 (they are also disabled in altered_table_def) */
16222
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 auto td = std::unique_ptr<dd::Table>(table_def->clone());
16223
6/10
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 9 times.
✓ Branch 9 taken 5 times.
14 for (const auto index : *td->indexes()) {
16224
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 const char *dd_index_name = index->name().c_str();
16225
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 9 times.
22 for (i = 0; i < alter_info->delayed_key_count; i++) {
16226
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9 times.
13 if (strcmp(alter_info->delayed_key_info[i].name, dd_index_name) == 0) {
16227 4 index->set_disabled(true);
16228 }
16229 }
16230 }
16231
16232
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (table->file->ha_prepare_inplace_alter_table(table, &ha_alter_info,
16233 5 table_def, td.get()) ||
16234
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 table->file->ha_inplace_alter_table(table, &ha_alter_info, table_def,
16235
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
10 td.get()) ||
16236
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 table->file->ha_commit_inplace_alter_table(table, &ha_alter_info, true,
16237 table_def, td.get())) {
16238 table->file->ha_commit_inplace_alter_table(table, &ha_alter_info, false,
16239 table_def, td.get());
16240 return true;
16241 }
16242
16243 5 return false;
16244 5 }
16245
16246 /*
16247 Restore secondary keys previously removed in remove_secondary_keys.
16248 */
16249
16250 5 static bool restore_secondary_keys(
16251 THD *thd, HA_CREATE_INFO *create_info, TABLE *table, Alter_info *alter_info,
16252 dd::Table *altered_table_def,
16253 std::vector<dd::Index *> *dd_disabled_sec_keys) {
16254 uint i;
16255
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 DBUG_ENTER("restore_secondary_keys");
16256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 assert(alter_info->delayed_key_count > 0);
16257
16258
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 THD_STAGE_INFO(thd, stage_restoring_secondary_keys);
16259
16260 /*
16261 Create Alter_info for the table and fill create_list with fields
16262 definitions. Not that fields not changed, so we set field==ogrig_field.
16263 */
16264
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 Alter_info alter_info_new(thd->mem_root);
16265 Field **f_ptr, *field;
16266
16267
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (f_ptr = table->field; (field = *f_ptr); f_ptr++) {
16268
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 Create_field *new_field = new (thd->mem_root) Create_field(field, field);
16269
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 alter_info_new.create_list.push_back(new_field);
16270 }
16271
16272 Alter_inplace_info ha_alter_info(create_info, &alter_info_new, false,
16273 5 alter_info->delayed_key_info, table->s->keys,
16274 5 thd->work_part_info);
16275
16276 5 ha_alter_info.handler_flags = Alter_inplace_info::ADD_INDEX;
16277 5 ha_alter_info.index_add_count = alter_info->delayed_key_count;
16278
16279 5 ha_alter_info.index_add_buffer =
16280
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 (uint *)thd->alloc(sizeof(uint) * alter_info->delayed_key_count);
16281
16282 /* Clone current version of table def */
16283
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 auto td = std::unique_ptr<dd::Table>(altered_table_def->clone());
16284
16285
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 for (const auto index : *dd_disabled_sec_keys) {
16286 7 index->set_disabled(false);
16287 }
16288
16289 /* Fill index_add_buffer with key indexes from key_info_buffer */
16290
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 for (i = 0; i < alter_info->delayed_key_count; i++)
16291 7 ha_alter_info.index_add_buffer[i] = i;
16292
16293
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (table->file->check_if_supported_inplace_alter(table, &ha_alter_info) ==
16294 HA_ALTER_INPLACE_NOT_SUPPORTED)
16295 DBUG_RETURN(-1);
16296
16297 /* Use previously clonned altered_table_def (the one with disabled keys)
16298 and enable keys */
16299
16300
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
5 if (table->file->ha_prepare_inplace_alter_table(
16301 5 table, &ha_alter_info, td.get(), altered_table_def) ||
16302
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 table->file->ha_inplace_alter_table(table, &ha_alter_info, td.get(),
16303
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
8 altered_table_def) ||
16304
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 table->file->ha_commit_inplace_alter_table(table, &ha_alter_info, true,
16305 4 td.get(), altered_table_def)) {
16306 table->file->ha_commit_inplace_alter_table(table, &ha_alter_info, false,
16307 td.get(), altered_table_def);
16308 DBUG_RETURN(true);
16309 }
16310
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 DBUG_RETURN(false);
16311 4 }
16312
16313 /**
16314 Auxiliary class implementing RAII principle for getting permission for/
16315 notification about finished ALTER TABLE from interested storage engines.
16316
16317 @see handlerton::notify_alter_table for details.
16318 */
16319
16320 class Alter_table_hton_notification_guard {
16321 public:
16322 92035 Alter_table_hton_notification_guard(THD *thd, const MDL_key *key)
16323 92035 : m_hton_notified(false), m_thd(thd), m_key(*key) {}
16324
16325 90851 bool notify() {
16326
1/2
✓ Branch 0 taken 90851 times.
✗ Branch 1 not taken.
90851 if (!ha_notify_alter_table(m_thd, &m_key, HA_NOTIFY_PRE_EVENT)) {
16327 90851 m_hton_notified = true;
16328 90851 return false;
16329 }
16330 my_error(ER_LOCK_REFUSED_BY_ENGINE, MYF(0));
16331 return true;
16332 }
16333
16334 91419 ~Alter_table_hton_notification_guard() {
16335
2/2
✓ Branch 0 taken 90236 times.
✓ Branch 1 taken 1183 times.
91419 if (m_hton_notified)
16336 90236 (void)ha_notify_alter_table(m_thd, &m_key, HA_NOTIFY_POST_EVENT);
16337 91419 }
16338
16339 private:
16340 bool m_hton_notified;
16341 THD *m_thd;
16342 const MDL_key m_key;
16343 };
16344
16345 /**
16346 Check if we are changing the SRID specification on a geometry column that
16347 has a spatial index. If that is the case, reject the change since allowing
16348 geometries with different SRIDs in a spatial index will make the index
16349 useless.
16350
16351 @param alter_info Structure describing the changes to be carried out.
16352
16353 @retval true if all of the geometry columns can be altered/changed as
16354 requested
16355 @retval false if the change is considered invalid
16356 */
16357 88255 static bool is_alter_geometry_column_valid(Alter_info *alter_info) {
16358 Create_field *create_field;
16359
1/2
✓ Branch 0 taken 88255 times.
✗ Branch 1 not taken.
88255 List_iterator<Create_field> list_it(alter_info->create_list);
16360
16361
2/2
✓ Branch 0 taken 966483 times.
✓ Branch 1 taken 88244 times.
1054727 while ((create_field = list_it++)) {
16362 1963134 if (create_field->change != nullptr &&
16363
6/6
✓ Branch 0 taken 30168 times.
✓ Branch 1 taken 936315 times.
✓ Branch 2 taken 124 times.
✓ Branch 3 taken 30044 times.
✓ Branch 4 taken 99 times.
✓ Branch 5 taken 966384 times.
966607 create_field->sql_type == MYSQL_TYPE_GEOMETRY &&
16364
3/4
✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
✓ Branch 3 taken 25 times.
124 create_field->field->type() == MYSQL_TYPE_GEOMETRY) {
16365 const Field_geom *geom_field =
16366 99 down_cast<const Field_geom *>(create_field->field);
16367 99 const TABLE_SHARE *share = geom_field->table->s;
16368
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 40 times.
99 if (geom_field->get_srid() != create_field->m_srid) {
16369 /*
16370 Check if there is a spatial index on this column. If that is the
16371 case, reject the change.
16372 */
16373
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 48 times.
59 for (uint i = 0; i < share->keys; ++i) {
16374
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
22 if (geom_field->key_start.is_set(i) &&
16375
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 share->key_info[i].flags & HA_SPATIAL) {
16376 11 my_error(ER_CANNOT_ALTER_SRID_DUE_TO_INDEX, MYF(0),
16377
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 geom_field->field_name);
16378 11 return false;
16379 }
16380 }
16381 }
16382 }
16383 }
16384 88244 return true;
16385 }
16386
16387 /**
16388 Add MDL requests for exclusive lock on names of the foreign keys to
16389 be dropped by ALTER TABLE operation to the lock requests list.
16390
16391 @param thd Thread context.
16392 @param db Table's database before ALTER TABLE
16393 operation.
16394 @param alter_info Alter_info object with the list of FKs
16395 to be dropped.
16396 @param table_def dd::Table describing the table before
16397 ALTER operation.
16398 @param[in,out] mdl_requests List to which MDL requests are to be added.
16399
16400 @retval operation outcome, false if no error.
16401 */
16402
16403 90545 static bool collect_fk_names_for_dropped_fks(THD *thd, const char *db,
16404 const Alter_info *alter_info,
16405 const dd::Table *table_def,
16406 MDL_request_list *mdl_requests) {
16407
2/2
✓ Branch 0 taken 11591 times.
✓ Branch 1 taken 90545 times.
102136 for (const Alter_drop *drop : alter_info->drop_list) {
16408
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 11527 times.
11591 if (drop->type == Alter_drop::FOREIGN_KEY) {
16409
6/10
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 64 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 71 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 71 times.
✓ Branch 9 taken 13 times.
84 for (const dd::Foreign_key *fk : table_def->foreign_keys()) {
16410
2/4
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 71 times.
✗ Branch 3 not taken.
71 if (my_strcasecmp(system_charset_info, drop->name,
16411
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 20 times.
71 fk->name().c_str()) == 0) {
16412 /*
16413 Since foreign key names are case-insensitive we need to lowercase
16414 them before passing to MDL subsystem.
16415 */
16416 char fk_name[NAME_LEN + 1];
16417
2/4
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
✗ Branch 3 not taken.
51 strmake(fk_name, fk->name().c_str(), NAME_LEN);
16418
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 my_casedn_str(system_charset_info, fk_name);
16419
16420
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 MDL_request *mdl_request = new (thd->mem_root) MDL_request;
16421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (mdl_request == nullptr) return true;
16422
16423
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 MDL_REQUEST_INIT(mdl_request, MDL_key::FOREIGN_KEY, db, fk_name,
16424 MDL_EXCLUSIVE, MDL_STATEMENT);
16425
16426
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 mdl_requests->push_front(mdl_request);
16427 51 break;
16428 }
16429 }
16430 }
16431 }
16432 90545 return false;
16433 }
16434
16435 /**
16436 This function will check if we are dropping a functional index. In that
16437 case, the function will add any related hidden generated columns to the drop
16438 list as well.
16439
16440 @param thd Thread handler
16441 @param alter_info The changes to be carried out
16442 @param table_list The current table reference
16443
16444 @retval true on error (my_error is already called)
16445 @retval false on success
16446 */
16447 91870 static bool handle_drop_functional_index(THD *thd, Alter_info *alter_info,
16448 TABLE_LIST *table_list) {
16449 // Check if we are dropping a functional index. In that case, we need to drop
16450 // the source column as well.
16451
2/2
✓ Branch 0 taken 12062 times.
✓ Branch 1 taken 91869 times.
103931 for (const Alter_drop *drop : alter_info->drop_list) {
16452
2/2
✓ Branch 0 taken 8793 times.
✓ Branch 1 taken 3269 times.
12062 if (drop->type == Alter_drop::KEY) {
16453
2/2
✓ Branch 0 taken 16508 times.
✓ Branch 1 taken 8793 times.
25301 for (uint j = 0; j < table_list->table->s->keys; j++) {
16454 16508 const KEY &key_info = table_list->table->s->key_info[j];
16455
2/2
✓ Branch 0 taken 7934 times.
✓ Branch 1 taken 8574 times.
16508 if (my_strcasecmp(system_charset_info, key_info.name, drop->name) ==
16456 0) {
16457
2/2
✓ Branch 0 taken 12044 times.
✓ Branch 1 taken 7934 times.
19978 for (uint k = 0; k < key_info.user_defined_key_parts; ++k) {
16458 12044 const KEY_PART_INFO &key_part = key_info.key_part[k];
16459
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 11971 times.
12044 if (key_part.field->is_field_for_functional_index()) {
16460 // Add column to drop list
16461 Alter_drop *column_drop = new (thd->mem_root)
16462
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 Alter_drop(Alter_drop::COLUMN, key_part.field->field_name);
16463
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 alter_info->drop_list.push_back(column_drop);
16464 73 alter_info->flags |= Alter_info::ALTER_DROP_COLUMN;
16465 }
16466 }
16467 }
16468 }
16469
2/2
✓ Branch 0 taken 3102 times.
✓ Branch 1 taken 167 times.
3269 } else if (drop->type == Alter_drop::COLUMN) {
16470
2/2
✓ Branch 0 taken 18992 times.
✓ Branch 1 taken 3101 times.
22093 for (uint j = 0; j < table_list->table->s->fields; j++) {
16471 18992 Field *field = table_list->table->s->field[j];
16472 18992 if (my_strcasecmp(system_charset_info, field->field_name, drop->name) ==
16473
6/6
✓ Branch 0 taken 3093 times.
✓ Branch 1 taken 15899 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3092 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 18991 times.
22085 0 &&
16474 3093 field->is_field_for_functional_index()) {
16475 1 my_error(ER_CANNOT_DROP_COLUMN_FUNCTIONAL_INDEX, MYF(0),
16476 field->field_name);
16477 1 return true;
16478 }
16479 }
16480 }
16481 }
16482
16483 91869 return false;
16484 }
16485
16486 /**
16487 This function will check if we are renaming a functional index. In that case,
16488 the function will add a "change column" operation to the create list that
16489 renames any affected hidden generated column(s). The reason is that the hidden
16490 generated column name is generated by MD5(key name + key part number), so a
16491 change in the index name will change the name of the column.
16492
16493 @param thd thread handler
16494 @param alter_info the changes to be carried out.
16495 @param table_list a reference to the current table
16496
16497 @retval true OOM
16498 @retval false success
16499 */
16500 215 static bool handle_rename_functional_index(THD *thd, Alter_info *alter_info,
16501 TABLE_LIST *table_list) {
16502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 215 times.
215 assert(alter_info->flags & Alter_info::ALTER_RENAME_INDEX);
16503
16504 220 for (const Alter_rename_key *alter_rename_key :
16505
2/2
✓ Branch 0 taken 220 times.
✓ Branch 1 taken 215 times.
435 alter_info->alter_rename_key_list) {
16506 // Find the matching existing index
16507
2/2
✓ Branch 0 taken 590 times.
✓ Branch 1 taken 47 times.
637 for (uint j = 0; j < table_list->table->s->keys; ++j) {
16508 590 const KEY &key = table_list->table->s->key_info[j];
16509 590 if (my_strcasecmp(system_charset_info, key.name,
16510
2/2
✓ Branch 0 taken 173 times.
✓ Branch 1 taken 417 times.
590 alter_rename_key->old_name) == 0) {
16511
2/2
✓ Branch 0 taken 285 times.
✓ Branch 1 taken 173 times.
458 for (uint k = 0; k < key.actual_key_parts; ++k) {
16512 285 const KEY_PART_INFO &key_part = key.key_part[k];
16513
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 276 times.
285 if (key_part.field->is_field_for_functional_index()) {
16514 // Rename the field. But use the field that exists in the table
16515 // object. In particular, the field object in KEY_PART_INFO does
16516 // not have the generated column expression.
16517
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 9 times.
113 for (uint l = 0; l < table_list->table->s->fields; ++l) {
16518 104 Field *field = table_list->table->field[l];
16519
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 95 times.
104 if (field->field_index() == key_part.field->field_index()) {
16520 Create_field *new_create_field =
16521
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 new (thd->mem_root) Create_field(field, nullptr);
16522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (new_create_field == nullptr) {
16523 return true; /* purecov: deadcode */
16524 }
16525
16526 9 new_create_field->change = field->field_name;
16527 9 new_create_field->after = nullptr;
16528 9 new_create_field->field_name =
16529
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 make_functional_index_column_name(
16530 9 alter_rename_key->new_name, k, alter_info->create_list,
16531 thd->mem_root);
16532
16533 9 alter_info->create_list.push_back(new_create_field);
16534 9 alter_info->flags |= Alter_info::ALTER_CHANGE_COLUMN;
16535 }
16536 }
16537 }
16538 }
16539
16540 173 break;
16541 }
16542 }
16543 }
16544
16545 215 return false;
16546 }
16547
16548 class Diagnostics_area_man {
16549 THD *m_thd;
16550 Diagnostics_area *da_prev;
16551 Diagnostics_area da;
16552
16553 public:
16554 Diagnostics_area_man(THD *thd)
16555 : m_thd(thd), da_prev(thd->get_stmt_da()), da(false) {
16556 // Don't copy existing conditions from the old DA so we don't get them
16557 // twice when we call copy_non_errors_from_da below.
16558 m_thd->push_diagnostics_area(&da, false);
16559 }
16560
16561 ~Diagnostics_area_man() {
16562 m_thd->pop_diagnostics_area();
16563
16564 if (da.is_error()) {
16565 da_prev->set_error_status(da.mysql_errno(), da.message_text(),
16566 da.returned_sqlstate());
16567 da_prev->push_warning(m_thd, da.mysql_errno(), da.returned_sqlstate(),
16568 Sql_condition::SL_ERROR, da.message_text());
16569 }
16570 }
16571 };
16572
16573 /**
16574 Alter table
16575
16576 @param thd Thread handle
16577 @param new_db If there is a RENAME clause
16578 @param new_name If there is a RENAME clause
16579 @param create_info Information from the parsing phase about new
16580 table properties.
16581 @param table_list The table to change.
16582 @param alter_info Lists of fields, keys to be changed, added
16583 or dropped.
16584
16585 @retval true Error
16586 @retval false Success
16587
16588 This is a veery long function and is everything but the kitchen sink :)
16589 It is used to alter a table and not only by ALTER TABLE but also
16590 CREATE|DROP INDEX are mapped on this function.
16591
16592 When the ALTER TABLE statement just does a RENAME or ENABLE|DISABLE KEYS,
16593 or both, then this function short cuts its operation by renaming
16594 the table and/or enabling/disabling the keys. In this case, the FRM is
16595 not changed, directly by mysql_alter_table. However, if there is a
16596 RENAME + change of a field, or an index, the short cut is not used.
16597 See how `create_list` is used to generate the new FRM regarding the
16598 structure of the fields. The same is done for the indices of the table.
16599
16600 Altering a table can be done in two ways. The table can be modified
16601 directly using an in-place algorithm, or the changes can be done using
16602 an intermediate temporary table (copy). In-place is the preferred
16603 algorithm as it avoids copying table data. The storage engine
16604 selects which algorithm to use in check_if_supported_inplace_alter()
16605 based on information about the table changes from fill_alter_inplace_info().
16606 */
16607
16608 92067 bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name,
16609 HA_CREATE_INFO *create_info, TABLE_LIST *table_list,
16610 Alter_info *alter_info) {
16611
1/2
✓ Branch 0 taken 92067 times.
✗ Branch 1 not taken.
92067 DBUG_TRACE;
16612
16613 /*
16614 This change is necessary for MyRocks at
16615 https://github.com/facebook/mysql-5.6/commit/1046d4f7074
16616
16617 Populate the actual user table name which is getting altered.
16618 This flag will be used to put some additional constraints on user tables.*/
16619
6/10
✓ Branch 0 taken 92067 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 92067 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 92067 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 92067 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 50752 times.
✓ Branch 9 taken 41315 times.
92067 if (!dd::get_dictionary()->is_system_table_name(table_list->db,
16620 table_list->table_name)) {
16621
1/2
✓ Branch 0 taken 50752 times.
✗ Branch 1 not taken.
50752 create_info->actual_user_table_name = table_list->table_name;
16622 }
16623 /*
16624 Check if we attempt to alter mysql.slow_log or
16625 mysql.general_log table and return an error if
16626 it is the case.
16627 TODO: this design is obsolete and will be removed.
16628 */
16629 enum_log_table_type table_kind =
16630
1/2
✓ Branch 0 taken 92067 times.
✗ Branch 1 not taken.
92067 query_logger.check_if_log_table(table_list, false);
16631
16632
2/2
✓ Branch 0 taken 1001 times.
✓ Branch 1 taken 91066 times.
92067 if (table_kind != QUERY_LOG_NONE) {
16633 /* Disable alter of enabled query log tables */
16634
3/4
✓ Branch 0 taken 1001 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 998 times.
1001 if (query_logger.is_log_table_enabled(table_kind)) {
16635
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_BAD_LOG_STATEMENT, MYF(0), "ALTER");
16636 3 return true;
16637 }
16638
16639 /* Disable alter of log tables to unsupported engine */
16640
2/2
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 791 times.
998 if ((create_info->used_fields & HA_CREATE_USED_ENGINE) &&
16641
1/2
✓ Branch 0 taken 207 times.
✗ Branch 1 not taken.
207 (!create_info->db_type || /* unknown engine */
16642
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 206 times.
207 !(create_info->db_type->flags & HTON_SUPPORT_LOG_TABLES))) {
16643
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_UNSUPORTED_LOG_ENGINE, MYF(0));
16644 1 return true;
16645 }
16646
16647
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 996 times.
997 if (alter_info->flags & Alter_info::ALTER_PARTITION) {
16648
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_WRONG_USAGE, MYF(0), "PARTITION", "log table");
16649 1 return true;
16650 }
16651 }
16652
16653 // Reject request to ALTER TABLE with START TRANSACTION.
16654
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 92061 times.
92062 if (create_info->m_transactional_ddl) {
16655
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_NOT_ALLOWED_WITH_START_TRANSACTION, MYF(0),
16656 "with ALTER TABLE command.");
16657 1 return true;
16658 }
16659
16660
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 92026 times.
92061 if (alter_info->with_validation != Alter_info::ALTER_VALIDATION_DEFAULT &&
16661
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 30 times.
35 !(alter_info->flags &
16662 (Alter_info::ALTER_ADD_COLUMN | Alter_info::ALTER_CHANGE_COLUMN))) {
16663
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_error(ER_WRONG_USAGE, MYF(0), "ALTER", "WITH VALIDATION");
16664 5 return true;
16665 }
16666
16667
2/2
✓ Branch 0 taken 18993 times.
✓ Branch 1 taken 73063 times.
92056 if ((alter_info->flags & Alter_info::ALTER_ADD_COLUMN) ==
16668 Alter_info::ALTER_ADD_COLUMN) {
16669
6/10
✓ Branch 0 taken 18993 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18993 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 31080 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 50065 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 31080 times.
✓ Branch 9 taken 18985 times.
50065 for (auto create_field : alter_info->create_list) {
16670
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 30953 times.
31080 if (create_field.m_default_val_expr) {
16671 // ALTER TABLE .. DEFAULT (NDF function) should be rejected for mixed or
16672 // row binlog_format. For statement binlog_format it should be allowed
16673 // to continue and warning should be logged and/or pushed to the client
16674
5/6
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 119 times.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 119 times.
254 if ((thd->variables.option_bits & OPTION_BIN_LOG) &&
16675 127 thd->lex->is_stmt_unsafe(
16676 Query_tables_list::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION)) {
16677
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if (thd->variables.binlog_format == BINLOG_FORMAT_STMT) {
16678
8/16
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
2 LogErr(WARNING_LEVEL, ER_SERVER_BINLOG_UNSAFE_SYSTEM_FUNCTION,
16679 "ALTER TABLE .. DEFAULT (NDF function)");
16680
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 push_warning(thd, Sql_condition::SL_WARNING,
16681 ER_BINLOG_UNSAFE_SYSTEM_FUNCTION,
16682 ER_THD(thd, ER_BINLOG_UNSAFE_SYSTEM_FUNCTION));
16683 2 break;
16684 } else {
16685
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(ER_BINLOG_UNSAFE_SYSTEM_FUNCTION, MYF(0));
16686 6 return true;
16687 }
16688 }
16689 }
16690 }
16691 }
16692
16693 // LOCK clause doesn't make any sense for ALGORITHM=INSTANT.
16694
2/2
✓ Branch 0 taken 1029 times.
✓ Branch 1 taken 91021 times.
92050 if (alter_info->requested_algorithm ==
16695 1029 Alter_info::ALTER_TABLE_ALGORITHM_INSTANT &&
16696
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1026 times.
1029 alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_DEFAULT) {
16697
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_WRONG_USAGE, MYF(0), "ALGORITHM=INSTANT",
16698 "LOCK=NONE/SHARED/EXCLUSIVE");
16699 3 return true;
16700 }
16701
16702
1/2
✓ Branch 0 taken 92047 times.
✗ Branch 1 not taken.
92047 THD_STAGE_INFO(thd, stage_init);
16703
16704 // Reject invalid usage of the 'mysql' tablespace.
16705
5/8
✓ Branch 0 taken 92047 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 92047 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 92047 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✓ Branch 7 taken 92038 times.
92047 if (dd::invalid_tablespace_usage(thd, table_list->db, table_list->table_name,
16706 create_info))
16707 9 return true;
16708
16709 /*
16710 Assign target tablespace name to enable locking in lock_table_names().
16711 Reject invalid name lengths. Names will be validated after the table is
16712 opened and the SE (needed for SE specific validation) is identified.
16713 */
16714
2/2
✓ Branch 0 taken 5234 times.
✓ Branch 1 taken 86804 times.
92038 if (create_info->tablespace) {
16715
3/4
✓ Branch 0 taken 5234 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 5232 times.
5234 if (validate_tablespace_name_length(create_info->tablespace)) return true;
16716
16717
2/4
✓ Branch 0 taken 5232 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5232 times.
5232 if (lex_string_strmake(thd->mem_root, &table_list->target_tablespace_name,
16718 create_info->tablespace,
16719 strlen(create_info->tablespace))) {
16720 my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
16721 return true;
16722 }
16723 }
16724
16725 /* Validate that AUTOEXTEND_SIZE option is not specified for
16726 temporary tables */
16727
2/2
✓ Branch 0 taken 1185 times.
✓ Branch 1 taken 90851 times.
92036 if (is_temporary_table(table_list)) {
16728
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1184 times.
1185 if (create_info->m_implicit_tablespace_autoextend_size > 0) {
16729
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_CANNOT_USE_AUTOEXTEND_SIZE_CLAUSE, MYF(0), "temporary");
16730 1 return true;
16731 }
16732 }
16733
16734 /*
16735 Reject invalid tablespace name lengths specified for partitions.
16736 Names will be validated after the table has been opened.
16737 */
16738
2/4
✓ Branch 0 taken 92035 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 92035 times.
92035 if (validate_partition_tablespace_name_lengths(thd->lex->part_info))
16739 return true;
16740
16741 /*
16742 Assign the partition info, so that the locks on tablespaces
16743 assigned for any new partitions added would be acquired during
16744 open_table.
16745 */
16746 92035 thd->work_part_info = thd->lex->part_info;
16747
16748 /*
16749 Code below can handle only base tables so ensure that we won't open a view.
16750 Note that RENAME TABLE the only ALTER clause which is supported for views
16751 has been already processed.
16752 */
16753 92035 table_list->required_type = dd::enum_table_type::BASE_TABLE;
16754
16755 /*
16756 If we are about to ALTER non-temporary table we need to get permission
16757 from/notify interested storage engines.
16758 */
16759 Alter_table_hton_notification_guard notification_guard(
16760
1/2
✓ Branch 0 taken 92035 times.
✗ Branch 1 not taken.
92035 thd, &table_list->mdl_request.key);
16761
16762
5/8
✓ Branch 0 taken 90851 times.
✓ Branch 1 taken 1184 times.
✓ Branch 2 taken 90851 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 90851 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 92035 times.
92035 if (!is_temporary_table(table_list) && notification_guard.notify())
16763 return true;
16764
16765 92035 Alter_table_prelocking_strategy alter_prelocking_strategy;
16766
16767
3/4
✓ Branch 0 taken 89655 times.
✓ Branch 1 taken 2380 times.
✓ Branch 2 taken 89655 times.
✗ Branch 3 not taken.
92035 DEBUG_SYNC(thd, "alter_table_before_open_tables");
16768 uint tables_opened;
16769
1/2
✓ Branch 0 taken 92035 times.
✗ Branch 1 not taken.
92035 bool error = open_tables(thd, &table_list, &tables_opened, 0,
16770 &alter_prelocking_strategy);
16771
16772
3/4
✓ Branch 0 taken 89655 times.
✓ Branch 1 taken 2380 times.
✓ Branch 2 taken 89655 times.
✗ Branch 3 not taken.
92035 DEBUG_SYNC(thd, "alter_opened_table");
16773
16774
2/2
✓ Branch 0 taken 165 times.
✓ Branch 1 taken 91870 times.
92035 if (error) return true;
16775
16776 // If we are removing a functional index, add any related hidden generated
16777 // columns to the drop list as well.
16778
3/4
✓ Branch 0 taken 91870 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 91869 times.
91870 if (handle_drop_functional_index(thd, alter_info, table_list)) {
16779 1 return true;
16780 }
16781
16782 // If we are renaming a functional index, rename any related hidden generated
16783 // columns as well.
16784
2/2
✓ Branch 0 taken 215 times.
✓ Branch 1 taken 91654 times.
91869 if (alter_info->flags & Alter_info::ALTER_RENAME_INDEX) {
16785
2/4
✓ Branch 0 taken 215 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 215 times.
215 if (handle_rename_functional_index(thd, alter_info, table_list)) {
16786 return true; /* purecov: deadcode */
16787 }
16788 }
16789
16790 // Check tablespace name validity for the relevant engine.
16791 {
16792 // If there is no target handlerton, use the current.
16793 91869 const handlerton *target_handlerton = create_info->db_type;
16794
2/2
✓ Branch 0 taken 87959 times.
✓ Branch 1 taken 3910 times.
91869 if (target_handlerton == nullptr)
16795 87959 target_handlerton = table_list->table->file->ht;
16796
16797 /*
16798 Reject invalid tablespace names for the relevant engine, if the ALTER
16799 statement changes either tablespace or engine. We do this after the table
16800 has been opened because we need the handlerton and tablespace information.
16801 No need to validate if neither engine nor tablespace is changed, then the
16802 validation was done when the table was created.
16803 */
16804
4/4
✓ Branch 0 taken 86641 times.
✓ Branch 1 taken 5228 times.
✓ Branch 2 taken 3900 times.
✓ Branch 3 taken 82741 times.
91869 if (create_info->tablespace || create_info->db_type) {
16805 // If there is no target table level tablespace, use the current.
16806 9128 const char *target_tablespace = create_info->tablespace;
16807
2/2
✓ Branch 0 taken 3900 times.
✓ Branch 1 taken 5228 times.
9128 if (target_tablespace == nullptr)
16808 3900 target_tablespace = table_list->table->s->tablespace;
16809
16810 // Check the tablespace/engine combination.
16811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9128 times.
9128 assert(target_handlerton);
16812
4/4
✓ Branch 0 taken 6977 times.
✓ Branch 1 taken 2151 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 9122 times.
16105 if (target_tablespace != nullptr &&
16813
3/4
✓ Branch 0 taken 6977 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6971 times.
6977 validate_tablespace_name(TS_CMD_NOT_DEFINED, target_tablespace,
16814 target_handlerton))
16815 6 return true;
16816 }
16817
16818 // Reject invalid tablespace names specified for partitions.
16819
3/4
✓ Branch 0 taken 91863 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 91860 times.
91863 if (validate_partition_tablespace_names(thd->lex->part_info,
16820 target_handlerton))
16821 3 return true;
16822 }
16823
16824
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 91850 times.
91860 if (validate_secondary_engine_option(*alter_info, *create_info,
16825
1/2
✓ Branch 0 taken 91860 times.
✗ Branch 1 not taken.
91860 *table_list->table))
16826 10 return true;
16827
16828
2/4
✓ Branch 0 taken 91850 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 91850 times.
91850 if (lock_trigger_names(thd, table_list)) return true;
16829
16830 /*
16831 If we're in LOCK TABLE mode, we must lock the target tablespace name
16832 as well as the currently used tablesapces (since these may have been
16833 introduced by a previous ALTER while already in LOCK TABLE mode).
16834 */
16835
3/4
✓ Branch 0 taken 1223 times.
✓ Branch 1 taken 90627 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 91850 times.
93073 if (thd->locked_tables_mode &&
16836
2/4
✓ Branch 0 taken 1223 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1223 times.
1223 get_and_lock_tablespace_names(thd, table_list, nullptr,
16837 thd->variables.lock_wait_timeout, MYF(0))) {
16838 return true;
16839 }
16840
16841
1/2
✓ Branch 0 taken 91850 times.
✗ Branch 1 not taken.
91850 if (table_list->table->s->db_type() != create_info->db_type &&
16842
6/6
✓ Branch 0 taken 88885 times.
✓ Branch 1 taken 2965 times.
✓ Branch 2 taken 25515 times.
✓ Branch 3 taken 63370 times.
✓ Branch 4 taken 943 times.
✓ Branch 5 taken 90907 times.
117365 (alter_info->flags & Alter_info::ALTER_OPTIONS) &&
16843
2/2
✓ Branch 0 taken 943 times.
✓ Branch 1 taken 24572 times.
25515 (create_info->used_fields & HA_CREATE_USED_ENGINE)) {
16844
1/2
✓ Branch 0 taken 943 times.
✗ Branch 1 not taken.
943 handlerton *actual_hton = get_viable_handlerton_for_alter(
16845
1/2
✓ Branch 0 taken 943 times.
✗ Branch 1 not taken.
943 thd, *create_info, table_list->table->s->db_type());
16846
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 939 times.
943 if (actual_hton == nullptr) return true;
16847
16848 939 create_info->db_type = actual_hton;
16849 }
16850
16851 91846 const handlerton *hton = create_info->db_type;
16852
2/2
✓ Branch 0 taken 87942 times.
✓ Branch 1 taken 3904 times.
91846 if (hton == nullptr) {
16853
1/2
✓ Branch 0 taken 87942 times.
✗ Branch 1 not taken.
87942 hton = table_list->table->s->db_type();
16854 }
16855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 91846 times.
91846 assert(hton != nullptr);
16856
4/4
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 91805 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 91825 times.
91887 if ((alter_info->flags & Alter_info::ANY_ENGINE_ATTRIBUTE) != 0 &&
16857
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 ((hton->flags & HTON_SUPPORTS_ENGINE_ATTRIBUTE) == 0 &&
16858
3/4
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 20 times.
41 DBUG_EVALUATE_IF("simulate_engine_attribute_support", false, true))) {
16859
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 my_error(ER_ENGINE_ATTRIBUTE_NOT_SUPPORTED, MYF(0),
16860 ha_resolve_storage_engine_name(hton));
16861 21 return true;
16862 }
16863
16864 91825 TABLE *table = table_list->table;
16865
1/2
✓ Branch 0 taken 91825 times.
✗ Branch 1 not taken.
91825 table->use_all_columns();
16866 91825 MDL_ticket *mdl_ticket = table->mdl_ticket;
16867
16868 /*
16869 Prohibit changing of the UNION list of a non-temporary MERGE table
16870 under LOCK tables. It would be quite difficult to reuse a shrunk
16871 set of tables from the old table or to open a new TABLE object for
16872 an extended list and verify that they belong to locked tables.
16873 */
16874
2/2
✓ Branch 0 taken 90602 times.
✓ Branch 1 taken 1223 times.
91825 if ((thd->locked_tables_mode == LTM_LOCK_TABLES ||
16875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90602 times.
90602 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) &&
16876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1223 times.
1223 (create_info->used_fields & HA_CREATE_USED_UNION) &&
16877 (table->s->tmp_table == NO_TMP_TABLE)) {
16878 my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
16879 return true;
16880 }
16881
16882
1/2
✓ Branch 0 taken 91825 times.
✗ Branch 1 not taken.
91825 Alter_table_ctx alter_ctx(thd, table_list, tables_opened, new_db, new_name);
16883
16884 /*
16885 Acquire and keep schema locks until commit time, so the DD layer can
16886 safely assert that we have proper MDL on objects stored in the DD.
16887 */
16888 91825 dd::Schema_MDL_locker mdl_locker_1(thd), mdl_locker_2(thd);
16889 91825 const dd::Schema *schema = nullptr;
16890 91825 const dd::Schema *new_schema = nullptr;
16891 91825 const dd::Table *old_table_def = nullptr;
16892 /*
16893 This releaser allows us to keep uncommitted DD objects cached
16894 in the Dictionary_client until commit time.
16895 */
16896
1/2
✓ Branch 0 taken 91825 times.
✗ Branch 1 not taken.
91825 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
16897 367300 if (mdl_locker_1.ensure_locked(alter_ctx.db) ||
16898
2/4
✓ Branch 0 taken 91825 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91825 times.
✗ Branch 3 not taken.
91825 mdl_locker_2.ensure_locked(alter_ctx.new_db) ||
16899
6/14
✓ Branch 0 taken 91825 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91825 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 91825 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 91825 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 91825 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 91825 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
367300 thd->dd_client()->acquire(alter_ctx.db, &schema) ||
16900
5/12
✓ Branch 0 taken 91825 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91825 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 91825 times.
✓ Branch 6 taken 91825 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 91825 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
183650 thd->dd_client()->acquire(alter_ctx.new_db, &new_schema))
16901 return true;
16902
16903
2/2
✓ Branch 0 taken 90642 times.
✓ Branch 1 taken 1183 times.
182467 if ((table->s->tmp_table == NO_TMP_TABLE) &&
16904
9/18
✓ Branch 0 taken 90642 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90642 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 90642 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 90642 times.
✓ Branch 8 taken 90642 times.
✓ Branch 9 taken 1183 times.
✓ Branch 10 taken 90642 times.
✓ Branch 11 taken 1183 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 91825 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
182467 thd->dd_client()->acquire(alter_ctx.db, alter_ctx.table_name,
16905 &old_table_def))
16906 return true;
16907
16908 // If this is a temporary table, the schema might not exist even
16909 // if we have successfully opened the table
16910
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 91824 times.
91825 if (schema == nullptr) {
16911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(table->s->tmp_table);
16912
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_BAD_DB_ERROR, MYF(0), alter_ctx.db);
16913 1 return true;
16914 }
16915
16916
3/4
✓ Branch 0 taken 90642 times.
✓ Branch 1 taken 1182 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 90642 times.
91824 assert((table->s->tmp_table != NO_TMP_TABLE) || old_table_def != nullptr);
16917
16918
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 91823 times.
91824 if (new_schema == nullptr) {
16919
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_BAD_DB_ERROR, MYF(0), alter_ctx.new_db);
16920 1 return true;
16921 }
16922
16923 /*
16924 Add old and new (if any) databases to the list of accessed databases
16925 for this statement. Needed for MTS.
16926 */
16927
1/2
✓ Branch 0 taken 91823 times.
✗ Branch 1 not taken.
91823 thd->add_to_binlog_accessed_dbs(alter_ctx.db);
16928
2/2
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 91580 times.
91823 if (alter_ctx.is_database_changed())
16929
1/2
✓ Branch 0 taken 243 times.
✗ Branch 1 not taken.
243 thd->add_to_binlog_accessed_dbs(alter_ctx.new_db);
16930
16931 // Ensure that triggers are in the same schema as their subject table.
16932
6/6
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 91580 times.
✓ Branch 2 taken 242 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 91821 times.
92065 if (alter_ctx.is_database_changed() && old_table_def != nullptr &&
16933
3/4
✓ Branch 0 taken 242 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 240 times.
242 old_table_def->has_trigger()) {
16934
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_TRG_IN_WRONG_SCHEMA, MYF(0));
16935 2 return true;
16936 }
16937
16938 /* Check that we are not trying to rename to an existing table */
16939
2/2
✓ Branch 0 taken 1092 times.
✓ Branch 1 taken 90729 times.
91821 if (alter_ctx.is_table_renamed()) {
16940
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1072 times.
1092 if (table->s->tmp_table != NO_TMP_TABLE) {
16941
3/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 18 times.
20 if (find_temporary_table(thd, alter_ctx.new_db, alter_ctx.new_name)) {
16942
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alter_ctx.new_alias);
16943 2 return true;
16944 }
16945 } else {
16946
1/2
✓ Branch 0 taken 1072 times.
✗ Branch 1 not taken.
1072 MDL_request_list mdl_requests;
16947
16948
1/2
✓ Branch 0 taken 1072 times.
✗ Branch 1 not taken.
1072 mdl_requests.push_front(&alter_ctx.target_mdl_request);
16949 /*
16950 If we are moving the table to a different database, we also
16951 need IX lock on the database name so that the target database
16952 is protected by MDL while the table is moved.
16953 */
16954
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 832 times.
1072 if (alter_ctx.is_database_changed())
16955
1/2
✓ Branch 0 taken 240 times.
✗ Branch 1 not taken.
240 mdl_requests.push_front(&alter_ctx.target_db_mdl_request);
16956
16957 /*
16958 Global intention exclusive lock must have been already acquired when
16959 table to be altered was open, so there is no need to do it here.
16960 */
16961
2/4
✓ Branch 0 taken 1072 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1072 times.
1072 assert(thd->mdl_context.owns_equal_or_stronger_lock(
16962 MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE));
16963
16964
2/4
✓ Branch 0 taken 1072 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1072 times.
1072 if (thd->mdl_context.acquire_locks(&mdl_requests,
16965 thd->variables.lock_wait_timeout))
16966 4 return true;
16967
16968
2/4
✓ Branch 0 taken 1072 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1072 times.
✗ Branch 3 not taken.
1072 DEBUG_SYNC(thd, "locked_table_name");
16969 /*
16970 Table maybe does not exist, but we got an exclusive lock
16971 on the name, now we can safely try to find out for sure.
16972 */
16973 1072 const dd::Abstract_table *at = nullptr;
16974
4/8
✓ Branch 0 taken 1072 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1072 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1072 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1072 times.
1072 if (thd->dd_client()->acquire(alter_ctx.new_db, alter_ctx.new_name, &at))
16975 return true;
16976
16977
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1068 times.
1072 if (at != nullptr) {
16978 /* Table will be closed in do_command() */
16979
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alter_ctx.new_alias);
16980 4 return true;
16981 }
16982 }
16983 }
16984
16985
2/2
✓ Branch 0 taken 87911 times.
✓ Branch 1 taken 3904 times.
91815 if (!create_info->db_type) {
16986
3/4
✓ Branch 0 taken 2892 times.
✓ Branch 1 taken 85019 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2892 times.
87911 if (table->part_info && create_info->used_fields & HA_CREATE_USED_ENGINE) {
16987 /*
16988 This case happens when the user specified
16989 ENGINE = x where x is a non-existing storage engine
16990 We set create_info->db_type to default_engine_type
16991 to ensure we don't change underlying engine type
16992 due to a erroneously given engine name.
16993 */
16994 create_info->db_type = table->part_info->default_engine_type;
16995 } else
16996
1/2
✓ Branch 0 taken 87911 times.
✗ Branch 1 not taken.
87911 create_info->db_type = table->s->db_type();
16997 }
16998
16999
3/4
✓ Branch 0 taken 91815 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87 times.
✓ Branch 3 taken 91728 times.
91815 if (check_engine(thd, alter_ctx.new_db, alter_ctx.new_name, create_info,
17000 alter_info))
17001 87 return true;
17002
17003 /*
17004 Do not allow change of storage engine if table participates in a foreign
17005 key. Even in cases when both source and target storage engines support
17006 foreign keys the fine details of what is supported might differ.
17007 */
17008
9/10
✓ Branch 0 taken 91728 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 859 times.
✓ Branch 3 taken 90869 times.
✓ Branch 4 taken 845 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 844 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 91725 times.
93417 if (create_info->db_type != table->s->db_type() && old_table_def != nullptr &&
17009
3/4
✓ Branch 0 taken 845 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 842 times.
1689 (old_table_def->foreign_keys().size() ||
17010
1/2
✓ Branch 0 taken 844 times.
✗ Branch 1 not taken.
844 old_table_def->foreign_key_parents().size())) {
17011
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_FK_CANNOT_CHANGE_ENGINE, MYF(0));
17012 3 return true;
17013 }
17014
17015 /*
17016 If foreign key is added then check permission to access parent table.
17017
17018 In function "check_fk_parent_table_access", create_info->db_type is used
17019 to identify whether engine supports FK constraint or not. Since
17020 create_info->db_type is set here, check to parent table access is delayed
17021 till this point for the alter operation.
17022 */
17023
3/4
✓ Branch 0 taken 244 times.
✓ Branch 1 taken 91481 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 91725 times.
91969 if ((alter_info->flags & Alter_info::ADD_FOREIGN_KEY) &&
17024
2/4
✓ Branch 0 taken 244 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 244 times.
244 check_fk_parent_table_access(thd, create_info, alter_info))
17025 return true;
17026
17027 91725 Foreign_key_parents_invalidator fk_invalidator;
17028
17029
2/2
✓ Branch 0 taken 90545 times.
✓ Branch 1 taken 1180 times.
91725 if (table->s->tmp_table == NO_TMP_TABLE) {
17030
1/2
✓ Branch 0 taken 90545 times.
✗ Branch 1 not taken.
90545 MDL_request_list mdl_requests;
17031
17032
2/4
✓ Branch 0 taken 90545 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 90545 times.
90545 if (collect_fk_parents_for_new_fks(
17033 thd, table_list->db, table_list->table_name, alter_info,
17034 MDL_SHARED_UPGRADABLE, nullptr, &mdl_requests, nullptr))
17035 2 return true;
17036
17037 /*
17038 Acquire SU locks on parent and child tables so we can access
17039 their definition while checking if this ALTER TABLE will break
17040 any FKs involving them.
17041
17042 TODO: Refine set of ALTER TABLE commands for which we do this.
17043 This is obviously necessary for ADD/DROP KEY and COLUMN
17044 modifications. But are there any other operations which
17045 might affect indexes somehow?
17046 */
17047
2/2
✓ Branch 0 taken 88502 times.
✓ Branch 1 taken 2043 times.
90545 if (!is_simple_rename_or_index_change(alter_info)) {
17048
2/4
✓ Branch 0 taken 88502 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 88502 times.
88502 if (collect_fk_parents_for_all_fks(thd, old_table_def, nullptr,
17049 MDL_SHARED_UPGRADABLE, &mdl_requests,
17050 nullptr))
17051 return true;
17052
17053
3/4
✓ Branch 0 taken 88502 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 842 times.
✓ Branch 3 taken 87660 times.
88502 if (create_info->db_type != table->s->db_type()) {
17054 /*
17055 By changing table's storage engine we might be introducing parent
17056 table for previously orphan foreign keys in the new SE. We need
17057 to lock child tables of such orphan foreign keys. OTOH it is safe
17058 to assume that if SE is changed table can't be parent in any
17059 foreign keys in old SE.
17060
17061 Note that here and in other similar places we assume that ALTER
17062 TABLE which combines change of SE and renaming of table is executed
17063 by changing SE first and then performing rename (this is closer to
17064 ALTER TABLE real implementation). Because of this such ALTER TABLEs
17065 need to pick up orphan foreign keys associated with old table names
17066 as well. Thus we use old table name to get list of orphans.
17067 */
17068
2/4
✓ Branch 0 taken 842 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 842 times.
842 assert(old_table_def->foreign_key_parents().size() == 0);
17069
17070
2/4
✓ Branch 0 taken 842 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 842 times.
842 if (collect_fk_children(thd, table_list->db, table_list->table_name,
17071 create_info->db_type, MDL_SHARED_UPGRADABLE,
17072 &mdl_requests))
17073 return true;
17074 } else {
17075
2/4
✓ Branch 0 taken 87660 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 87660 times.
87660 if (collect_fk_children(thd, old_table_def, MDL_SHARED_UPGRADABLE,
17076 &mdl_requests))
17077 return true;
17078 }
17079
17080
3/4
✓ Branch 0 taken 297 times.
✓ Branch 1 taken 88205 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 88502 times.
88799 if (alter_ctx.is_table_renamed() &&
17081
2/4
✓ Branch 0 taken 297 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 297 times.
297 collect_fk_children(thd, alter_ctx.new_db, alter_ctx.new_alias,
17082 create_info->db_type, MDL_SHARED_UPGRADABLE,
17083 &mdl_requests))
17084 return true;
17085 }
17086
17087 /*
17088 Lock names of foreign keys to be dropped.
17089
17090 Note that we can't lock names of foreign keys to be added yet
17091 because database in which they will be created depends on ALTER
17092 TABLE algorithm we are going to choose later.
17093 */
17094
2/4
✓ Branch 0 taken 90545 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 90545 times.
90545 if (collect_fk_names_for_dropped_fks(thd, table_list->db, alter_info,
17095 old_table_def, &mdl_requests))
17096 return true;
17097
17098 /*
17099 Under LOCK TABLES all parent tables must be locked at least in READ
17100 mode. Otherwise, our ALTER TABLE will leave after itself child table
17101 locked for WRITE, without corresponding parent tables locked and thus
17102 without ability to perform FK checks when child table is modified.
17103 */
17104
2/2
✓ Branch 0 taken 89323 times.
✓ Branch 1 taken 1222 times.
90545 if (thd->locked_tables_mode == LTM_LOCK_TABLES ||
17105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89323 times.
89323 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) {
17106 1222 MDL_request_list::Iterator it(mdl_requests);
17107 MDL_request *mdl_request;
17108
17109
3/4
✓ Branch 0 taken 1229 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1221 times.
1229 while ((mdl_request = it++) != nullptr) {
17110
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (mdl_request->key.mdl_namespace() != MDL_key::TABLE) continue;
17111
17112
4/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3 times.
4 if (!thd->mdl_context.owns_equal_or_stronger_lock(
17113 MDL_key::TABLE, mdl_request->key.db_name(),
17114 mdl_request->key.name(), MDL_SHARED_READ_ONLY)) {
17115
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 my_error(ER_TABLE_NOT_LOCKED, MYF(0), mdl_request->key.name());
17116 1 return true;
17117 }
17118 }
17119 }
17120
17121
3/4
✓ Branch 0 taken 583 times.
✓ Branch 1 taken 89961 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 90544 times.
91127 if (!mdl_requests.is_empty() &&
17122
2/4
✓ Branch 0 taken 583 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 583 times.
583 thd->mdl_context.acquire_locks(&mdl_requests,
17123 thd->variables.lock_wait_timeout))
17124 return true;
17125
17126
3/4
✓ Branch 0 taken 88164 times.
✓ Branch 1 taken 2380 times.
✓ Branch 2 taken 88164 times.
✗ Branch 3 not taken.
90544 DEBUG_SYNC(thd, "alter_table_after_mdl_lock_fk");
17127
17128 /*
17129 If we are executing ALTER TABLE RENAME under LOCK TABLES we also need
17130 to check that all previously orphan tables which reference new table
17131 name through foreign keys are locked for write. Otherwise this ALTER
17132 will leave after itself parent table locked for WRITE without child
17133 tables locked for WRITE. This will break FK LOCK TABLES invariants if
17134 some of previously orphan FKs have referential actions which update
17135 child table.
17136
17137 The same should be done when we are going to add parent table to
17138 previously orphan foreign keys by changing table storage engine.
17139
17140 In theory, we can reduce chance of MDL deadlocks by also checking at
17141 this stage that all child and parent tables for FKs in which this
17142 table participates are locked for WRITE (as we will have to acquire
17143 to exclusive MDLs on these tables later). But this is, probably, too
17144 severe restriction since many 3rd-party online ALTER tools use ALTER
17145 TABLE RENAME under LOCK TABLES and are unaware of it.
17146 */
17147
2/2
✓ Branch 0 taken 89323 times.
✓ Branch 1 taken 1221 times.
90544 if (thd->locked_tables_mode == LTM_LOCK_TABLES ||
17148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89323 times.
89323 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) {
17149
1/2
✓ Branch 0 taken 1221 times.
✗ Branch 1 not taken.
1221 MDL_request_list orphans_mdl_requests;
17150
17151
3/4
✓ Branch 0 taken 1221 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1216 times.
1221 if (create_info->db_type != table->s->db_type()) {
17152
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 assert(old_table_def->foreign_key_parents().size() == 0);
17153
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (collect_fk_children(thd, table_list->db, table_list->table_name,
17154 create_info->db_type, MDL_EXCLUSIVE,
17155 &orphans_mdl_requests))
17156 1 return true;
17157 }
17158
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 1192 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1221 times.
1250 if (alter_ctx.is_table_renamed() &&
17159
2/4
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 29 times.
29 collect_fk_children(thd, alter_ctx.new_db, alter_ctx.new_alias,
17160 create_info->db_type, MDL_EXCLUSIVE,
17161 &orphans_mdl_requests))
17162 return true;
17163
17164
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1219 times.
1221 if (!orphans_mdl_requests.is_empty()) {
17165 2 MDL_request_list::Iterator it(orphans_mdl_requests);
17166 MDL_request *mdl_request;
17167
17168
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1 times.
5 while ((mdl_request = it++) != nullptr) {
17169
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (mdl_request->key.mdl_namespace() != MDL_key::TABLE) continue;
17170
17171
4/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
2 if (!thd->mdl_context.owns_equal_or_stronger_lock(
17172 MDL_key::TABLE, mdl_request->key.db_name(),
17173 mdl_request->key.name(), MDL_SHARED_NO_READ_WRITE)) {
17174
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0),
17175 mdl_request->key.name());
17176 1 return true;
17177 }
17178 }
17179 }
17180 }
17181 }
17182
17183 /*
17184 If this is an ALTER TABLE and no explicit row type specified reuse
17185 the table's row type.
17186 Note : this is the same as if the row type was specified explicitly.
17187 */
17188
2/2
✓ Branch 0 taken 86410 times.
✓ Branch 1 taken 5313 times.
91723 if (create_info->row_type == ROW_TYPE_NOT_USED) {
17189 /* ALTER TABLE without explicit row type */
17190 86410 create_info->row_type = table->s->row_type;
17191 } else {
17192 /* ALTER TABLE with specific row type */
17193 5313 create_info->used_fields |= HA_CREATE_USED_ROW_FORMAT;
17194 }
17195
17196
8/14
✓ Branch 0 taken 91723 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91723 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 91721 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
91723 DBUG_PRINT("info", ("old type: %s new type: %s",
17197 ha_resolve_storage_engine_name(table->s->db_type()),
17198 ha_resolve_storage_engine_name(create_info->db_type)));
17199
1/2
✓ Branch 0 taken 91723 times.
✗ Branch 1 not taken.
91723 if (ha_check_storage_engine_flag(table->s->db_type(),
17200
5/6
✓ Branch 0 taken 91722 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 91722 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 91722 times.
183445 HTON_ALTER_NOT_SUPPORTED) ||
17201 91722 ha_check_storage_engine_flag(create_info->db_type,
17202 HTON_ALTER_NOT_SUPPORTED)) {
17203
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1 DBUG_PRINT("info", ("doesn't support alter"));
17204
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_ILLEGAL_HA, MYF(0), table_list->table_name);
17205 1 return true;
17206 }
17207
17208
1/2
✓ Branch 0 taken 91722 times.
✗ Branch 1 not taken.
91722 THD_STAGE_INFO(thd, stage_setup);
17209
17210
6/6
✓ Branch 0 taken 2060 times.
✓ Branch 1 taken 89662 times.
✓ Branch 2 taken 2043 times.
✓ Branch 3 taken 17 times.
✓ Branch 4 taken 2043 times.
✓ Branch 5 taken 89679 times.
91722 if (is_simple_rename_or_index_change(alter_info) && !table->s->tmp_table) {
17211 // This requires X-lock, no other lock levels supported.
17212
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2027 times.
2043 if (alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_DEFAULT &&
17213
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE) {
17214
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0), "LOCK=NONE/SHARED",
17215 "LOCK=EXCLUSIVE");
17216 10 return true;
17217 }
17218
1/2
✓ Branch 0 taken 2024 times.
✗ Branch 1 not taken.
2033 return simple_rename_or_index_change(thd, *new_schema, table_list,
17219 2024 alter_info->keys_onoff, &alter_ctx);
17220 }
17221
17222 /* We have to do full alter table. */
17223 89679 bool partition_changed = false;
17224 89679 partition_info *new_part_info = nullptr;
17225 {
17226
3/4
✓ Branch 0 taken 89679 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 137 times.
✓ Branch 3 taken 89542 times.
89679 if (prep_alter_part_table(thd, table, alter_info, create_info, &alter_ctx,
17227 &partition_changed, &new_part_info)) {
17228 137 return true;
17229 }
17230 }
17231
5/8
✓ Branch 0 taken 1093 times.
✓ Branch 1 taken 88449 times.
✓ Branch 2 taken 1093 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1093 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 89542 times.
89542 if (new_part_info != nullptr && alter_info->has_compressed_columns() &&
17232 !ha_check_storage_engine_flag(new_part_info->default_engine_type,
17233 HTON_SUPPORTS_COMPRESSED_COLUMNS)) {
17234 my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
17235 ha_resolve_storage_engine_name(new_part_info->default_engine_type),
17236 "COMPRESSED COLUMNS");
17237 return true;
17238 }
17239
17240 /*
17241 Store all columns that are going to be dropped, since we need this list
17242 when removing column statistics later. The reason we need to store it here,
17243 is that 'mysql_prepare_alter_table' may remove some of the columns from
17244 the drop_list.
17245 */
17246 89542 histograms::columns_set columns;
17247
3/4
✓ Branch 0 taken 89542 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12132 times.
✓ Branch 3 taken 89542 times.
101674 for (const auto column : alter_info->drop_list) {
17248
3/4
✓ Branch 0 taken 3174 times.
✓ Branch 1 taken 8958 times.
✓ Branch 2 taken 3174 times.
✗ Branch 3 not taken.
12132 if (column->type == Alter_drop::COLUMN) columns.emplace(column->name);
17249 }
17250 89542 const Alter_column *alter = nullptr;
17251 89542 uint i = 0;
17252
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 89542 times.
89902 while (i < alter_info->alter_list.size()) {
17253
1/2
✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
360 alter = alter_info->alter_list[i];
17254
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 259 times.
360 if (alter->change_type() == Alter_column::Type::RENAME_COLUMN)
17255
1/2
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
101 columns.emplace(alter->name);
17256 360 i++;
17257 }
17258
17259 Create_field *create_field;
17260
1/2
✓ Branch 0 taken 89542 times.
✗ Branch 1 not taken.
89542 List_iterator<Create_field> list_it(alter_info->create_list);
17261
2/2
✓ Branch 0 taken 61269 times.
✓ Branch 1 taken 89542 times.
150811 while ((create_field = list_it++)) {
17262
3/4
✓ Branch 0 taken 30303 times.
✓ Branch 1 taken 30966 times.
✓ Branch 2 taken 30303 times.
✗ Branch 3 not taken.
61269 if (create_field->change != nullptr) columns.emplace(create_field->change);
17263 }
17264
17265 /*
17266 Type of a constraint marked for DROP with DROP CONSTRAINT clause is unknown.
17267 Resolve type of a constraint by name.
17268 */
17269 89542 Drop_constraint_type_resolver drop_constraint_type_resolver(alter_info);
17270
5/6
✓ Branch 0 taken 89542 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 89504 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 89538 times.
89580 if (drop_constraint_type_resolver.is_type_resolution_needed() &&
17271
3/4
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 34 times.
38 (drop_constraint_type_resolver.resolve_constraints_type(thd, table,
17272 old_table_def)))
17273 4 return true;
17274
17275 /*
17276 Type of a constraint marked for ALTER with ALTER CONSTRAINT clause is
17277 unknown. Resolve type of a constraint by name.
17278 */
17279 89538 Enforce_constraint_type_resolver enforce_constraint_type_resolver(alter_info);
17280
5/6
✓ Branch 0 taken 89538 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 89518 times.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 89527 times.
89558 if (enforce_constraint_type_resolver.is_type_resolution_needed() &&
17281
3/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 9 times.
20 (enforce_constraint_type_resolver.resolve_constraints_type(
17282 thd, table, old_table_def)))
17283 11 return true;
17284
17285 // Prepare check constraints for alter table operation.
17286
3/4
✓ Branch 0 taken 89527 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 89499 times.
89527 if (prepare_check_constraints_for_alter(thd, table, alter_info, &alter_ctx))
17287 28 return true;
17288
17289
4/4
✓ Branch 0 taken 18924 times.
✓ Branch 1 taken 70575 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 89496 times.
108423 if ((alter_info->flags & Alter_info::ALTER_ADD_COLUMN) != 0 &&
17290
3/4
✓ Branch 0 taken 18924 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 18921 times.
18924 alter_info->has_compressed_columns()) {
17291
1/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 switch (alter_info->requested_algorithm) {
17292 3 case Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT:
17293
17294
3/26
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
3 DBUG_LOG("zip_dict",
17295 "ALTER query "
17296 << thd->query().str
17297 << " is using INPLACE for add column"
17298 " because one of the ADD COLUMN is compressed column");
17299
17300 3 alter_info->requested_algorithm =
17301 Alter_info::ALTER_TABLE_ALGORITHM_INPLACE;
17302 3 break;
17303 case Alter_info::ALTER_TABLE_ALGORITHM_INSTANT:
17304 // Not possible, error out.
17305 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0), "ALGORITHM=INSTANT",
17306 "ALGORITHM=INPLACE/COPY");
17307 return true;
17308 case Alter_info::ALTER_TABLE_ALGORITHM_COPY:
17309 case Alter_info::ALTER_TABLE_ALGORITHM_INPLACE:
17310 break;
17311 default:
17312 return 0;
17313 }
17314 }
17315
17316
3/4
✓ Branch 0 taken 89499 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1203 times.
✓ Branch 3 taken 88296 times.
89499 if (mysql_prepare_alter_table(thd, old_table_def, table, create_info,
17317 alter_info, &alter_ctx)) {
17318 1203 return true;
17319 }
17320
17321 // Check restrictions on ALTER TABLE operations that affects GIPK and PK.
17322
3/4
✓ Branch 0 taken 88296 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 88255 times.
88296 if (check_primary_key_alter_restrictions(thd, create_info->db_type,
17323 alter_info, table))
17324 41 return true;
17325
17326 /*
17327 Check if we are changing the SRID specification on a geometry column that
17328 has a spatial index. If that is the case, reject the change since allowing
17329 geometries with different SRIDs in a spatial index will make the index
17330 useless.
17331 */
17332
3/4
✓ Branch 0 taken 88255 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 88244 times.
88255 if (!is_alter_geometry_column_valid(alter_info)) return true;
17333
17334
2/4
✓ Branch 0 taken 88244 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 88244 times.
88244 if (set_table_default_charset(thd, create_info, *schema)) return true;
17335
17336 /*
17337 Use copy algorithm if:
17338 - old_alter_table system variable is set without in-place requested using
17339 the ALGORITHM clause.
17340 - Or if in-place is impossible for given operation.
17341 - Changes to partitioning needs to be handled using table copying
17342 algorithm unless the engine supports partitioning changes using
17343 in-place API (because it supports auto-partitioning or simply
17344 can do partitioning changes using in-place using mark-up in
17345 partition_info object).
17346 */
17347 176502 if ((thd->variables.old_alter_table &&
17348
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 alter_info->requested_algorithm !=
17349 13 Alter_info::ALTER_TABLE_ALGORITHM_INPLACE &&
17350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 alter_info->requested_algorithm !=
17351 88231 Alter_info::ALTER_TABLE_ALGORITHM_INSTANT) ||
17352
9/10
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 88230 times.
✓ Branch 2 taken 88231 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 85994 times.
✓ Branch 5 taken 2237 times.
✓ Branch 6 taken 1788 times.
✓ Branch 7 taken 84206 times.
✓ Branch 8 taken 2946 times.
✓ Branch 9 taken 85298 times.
90046 is_inplace_alter_impossible(table, create_info, alter_info) ||
17353 1788 (partition_changed &&
17354
3/6
✓ Branch 0 taken 1788 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1788 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1788 times.
✗ Branch 5 not taken.
1788 !(table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION) &&
17355
2/2
✓ Branch 0 taken 696 times.
✓ Branch 1 taken 1092 times.
1788 !new_part_info)) {
17356
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2934 times.
2946 if (alter_info->requested_algorithm ==
17357 Alter_info::ALTER_TABLE_ALGORITHM_INPLACE) {
17358
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0), "ALGORITHM=INPLACE",
17359 "ALGORITHM=COPY");
17360 12 return true;
17361 }
17362
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2929 times.
2934 if (alter_info->requested_algorithm ==
17363 Alter_info::ALTER_TABLE_ALGORITHM_INSTANT) {
17364
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0), "ALGORITHM=INSTANT",
17365 "ALGORITHM=COPY");
17366 5 return true;
17367 }
17368 2929 alter_info->requested_algorithm = Alter_info::ALTER_TABLE_ALGORITHM_COPY;
17369 }
17370
17371 /*
17372 If 'avoid_temporal_upgrade' mode is not enabled, then the
17373 pre MySQL 5.6.4 old temporal types if present is upgraded to the
17374 current format.
17375 */
17376
17377
1/2
✓ Branch 0 taken 88227 times.
✗ Branch 1 not taken.
88227 mysql_mutex_lock(&LOCK_global_system_variables);
17378 88227 bool check_temporal_upgrade = !avoid_temporal_upgrade;
17379
1/2
✓ Branch 0 taken 88227 times.
✗ Branch 1 not taken.
88227 mysql_mutex_unlock(&LOCK_global_system_variables);
17380
17381
1/2
✓ Branch 0 taken 88227 times.
✗ Branch 1 not taken.
88227 if (check_temporal_upgrade) {
17382
2/4
✓ Branch 0 taken 88227 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 88227 times.
88227 if (upgrade_old_temporal_types(thd, alter_info)) return true;
17383 }
17384
17385 /*
17386 ALTER TABLE ... ENGINE to the same engine is a common way to
17387 request table rebuild. Set ALTER_RECREATE flag to force table
17388 rebuild.
17389 */
17390
5/6
✓ Branch 0 taken 88227 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87387 times.
✓ Branch 3 taken 840 times.
✓ Branch 4 taken 2962 times.
✓ Branch 5 taken 85265 times.
175614 if (create_info->db_type == table->s->db_type() &&
17391
2/2
✓ Branch 0 taken 2962 times.
✓ Branch 1 taken 84425 times.
87387 create_info->used_fields & HA_CREATE_USED_ENGINE)
17392 2962 alter_info->flags |= Alter_info::ALTER_RECREATE;
17393
17394 /*
17395 If the old table had partitions and we are doing ALTER TABLE ...
17396 engine= <new_engine>, the new table must preserve the original
17397 partitioning. This means that the new engine is still the
17398 partitioning engine, not the engine specified in the parser.
17399 This is discovered in prep_alter_part_table, which in such case
17400 updates create_info->db_type.
17401 It's therefore important that the assignment below is done
17402 after prep_alter_part_table.
17403 */
17404 88227 handlerton *new_db_type = create_info->db_type;
17405
1/2
✓ Branch 0 taken 88227 times.
✗ Branch 1 not taken.
88227 handlerton *old_db_type = table->s->db_type();
17406 88227 TABLE *new_table = nullptr;
17407 88227 ha_rows copied = 0, deleted = 0;
17408
17409 /*
17410 Handling of symlinked tables:
17411 If no rename:
17412 Create new data file and index file on the same disk as the
17413 old data and index files.
17414 Copy data.
17415 Rename new data file over old data file and new index file over
17416 old index file.
17417 Symlinks are not changed.
17418
17419 If rename:
17420 Create new data file and index file on the same disk as the
17421 old data and index files. Create also symlinks to point at
17422 the new tables.
17423 Copy data.
17424 At end, rename intermediate tables, and symlinks to intermediate
17425 table, to final table name.
17426 Remove old table and old symlinks
17427
17428 If rename is made to another database:
17429 Create new tables in new database.
17430 Copy data.
17431 Remove old table and symlinks.
17432 */
17433 char index_file[FN_REFLEN], data_file[FN_REFLEN];
17434
17435
2/2
✓ Branch 0 taken 88127 times.
✓ Branch 1 taken 100 times.
88227 if (!alter_ctx.is_database_changed()) {
17436
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 88125 times.
88127 if (create_info->index_file_name) {
17437 /* Fix index_file_name to have 'tmp_name' as basename */
17438 2 my_stpcpy(index_file, alter_ctx.tmp_name);
17439 2 create_info->index_file_name =
17440
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 fn_same(index_file, create_info->index_file_name, 1);
17441 }
17442
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 88044 times.
88127 if (create_info->data_file_name) {
17443 /* Fix data_file_name to have 'tmp_name' as basename */
17444 83 my_stpcpy(data_file, alter_ctx.tmp_name);
17445 83 create_info->data_file_name =
17446
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 fn_same(data_file, create_info->data_file_name, 1);
17447 }
17448 } else {
17449 /* Ignore symlink if db is changed. */
17450 100 create_info->data_file_name = create_info->index_file_name = nullptr;
17451 }
17452
17453
3/4
✓ Branch 0 taken 85855 times.
✓ Branch 1 taken 2372 times.
✓ Branch 2 taken 85855 times.
✗ Branch 3 not taken.
88227 DEBUG_SYNC(thd, "alter_table_before_create_table_no_lock");
17454
4/6
✓ Branch 0 taken 88227 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 88226 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
88227 DBUG_EXECUTE_IF("sleep_before_create_table_no_lock", my_sleep(100000););
17455 /*
17456 Promote first timestamp column, when explicit_defaults_for_timestamp
17457 is not set
17458 */
17459
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 88167 times.
88227 if (!thd->variables.explicit_defaults_for_timestamp)
17460
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 promote_first_timestamp_column(&alter_info->create_list);
17461
17462 /*
17463 Create .FRM for new version of table with a temporary name.
17464 We don't log the statement, it will be logged later.
17465
17466 Keep information about keys in newly created table as it
17467 will be used later to construct Alter_inplace_info object
17468 and by fill_alter_inplace_info() call.
17469 */
17470 KEY *key_info;
17471 uint key_count;
17472 88227 FOREIGN_KEY *fk_key_info = nullptr;
17473 88227 uint fk_key_count = 0;
17474
17475 Alter_info::enum_enable_or_disable keys_onoff =
17476 176430 ((alter_info->keys_onoff == Alter_info::LEAVE_AS_IS &&
17477
3/4
✓ Branch 0 taken 88203 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 88197 times.
✓ Branch 3 taken 6 times.
88203 table->file->indexes_are_disabled())
17478
2/2
✓ Branch 0 taken 88203 times.
✓ Branch 1 taken 24 times.
176430 ? Alter_info::DISABLE
17479 88227 : alter_info->keys_onoff);
17480
17481 /*
17482 Take the X metadata lock on temporary name used for new version of
17483 the table. This ensures that concurrent I_S queries won't try to open it.
17484 */
17485
17486 88227 MDL_request tmp_name_mdl_request;
17487 88227 bool is_tmp_table = (table->s->tmp_table != NO_TMP_TABLE);
17488
17489 // Avoid these tables to be visible by I_S/SHOW queries.
17490 88227 create_info->m_hidden = !is_tmp_table;
17491
17492
2/2
✓ Branch 0 taken 87067 times.
✓ Branch 1 taken 1160 times.
88227 if (!is_tmp_table) {
17493
1/2
✓ Branch 0 taken 87067 times.
✗ Branch 1 not taken.
87067 MDL_REQUEST_INIT(&tmp_name_mdl_request, MDL_key::TABLE, alter_ctx.new_db,
17494 alter_ctx.tmp_name, MDL_EXCLUSIVE, MDL_STATEMENT);
17495
2/4
✓ Branch 0 taken 87067 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 87067 times.
87067 if (thd->mdl_context.acquire_lock(&tmp_name_mdl_request,
17496 thd->variables.lock_wait_timeout))
17497 return true;
17498 }
17499
17500 // Stop if we have invalid encryption clause.
17501
7/8
✓ Branch 0 taken 87067 times.
✓ Branch 1 taken 1160 times.
✓ Branch 2 taken 87067 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 101 times.
✓ Branch 5 taken 86966 times.
✓ Branch 6 taken 101 times.
✓ Branch 7 taken 88126 times.
88227 if (!is_tmp_table && validate_table_encryption(thd, create_info)) return true;
17502
17503 /*
17504 For temporary tables or tables in SEs supporting atomic DDL dd::Table
17505 object describing new version of table. This object will be created in
17506 memory in create_table_impl() and will not be put into the on-disk DD
17507 and DD Object Cache.
17508
17509 We become responsible for destroying this dd::Table object (for
17510 temporary tables until we pass its ownership to the TABLE_SHARE).
17511 */
17512 87519 std::unique_ptr<dd::Table> non_dd_table_def;
17513
17514 {
17515 88126 Disable_binlog_guard binlog_guard(thd);
17516 /* Prevent intermediate commits to invoke commit order */
17517 Implicit_substatement_state_guard substatement_guard(
17518 thd, enum_implicit_substatement_guard_mode ::
17519
1/2
✓ Branch 0 taken 88126 times.
✗ Branch 1 not taken.
88126 DISABLE_GTID_AND_SPCO_IF_SPCO_ACTIVE);
17520
1/2
✓ Branch 0 taken 88126 times.
✗ Branch 1 not taken.
88126 error = create_table_impl(
17521 thd, *new_schema, alter_ctx.new_db, alter_ctx.tmp_name,
17522 alter_ctx.table_name, alter_ctx.get_tmp_path(), create_info, alter_info,
17523 true, 0, true, true,
17524 /*
17525 If target SE supports atomic DDL do not store
17526 new table version in on-disk DD.
17527 It is not required to rollback statement in
17528 case of error and allows to keep correct names
17529 for pre-existing foreign keys in the dd::Table
17530 object for new table version.
17531 */
17532 88126 (new_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL), nullptr, &key_info,
17533 &key_count, keys_onoff, &fk_key_info, &fk_key_count, alter_ctx.fk_info,
17534 alter_ctx.fk_count, old_table_def,
17535 alter_ctx.fk_max_generated_name_number, &non_dd_table_def, nullptr);
17536 88126 }
17537
17538
2/2
✓ Branch 0 taken 8983 times.
✓ Branch 1 taken 79143 times.
88126 if (error) {
17539 /*
17540 Play it safe, rollback possible changes to the data-dictionary,
17541 so failed mysql_alter_table()/mysql_recreate_table() do not
17542 require rollback in the caller. Also do full rollback in unlikely
17543 case we have THD::transaction_rollback_request.
17544 */
17545
1/2
✓ Branch 0 taken 8983 times.
✗ Branch 1 not taken.
8983 trans_rollback_stmt(thd);
17546
1/2
✓ Branch 0 taken 8983 times.
✗ Branch 1 not taken.
8983 trans_rollback(thd);
17547 8983 return true;
17548 }
17549
17550 /*
17551 Atomic replacement of the table is possible only if both old and new
17552 storage engines support DDL atomicity.
17553 */
17554
2/2
✓ Branch 0 taken 62952 times.
✓ Branch 1 taken 16191 times.
142095 bool atomic_replace = (new_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) &&
17555
2/2
✓ Branch 0 taken 62257 times.
✓ Branch 1 taken 695 times.
62952 (old_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL);
17556
17557 /* Remember that we have not created table in storage engine yet. */
17558 79143 bool no_ha_table = true;
17559
17560 /* Indicates special case when we do ALTER TABLE which is really no-op. */
17561 79143 bool is_noop = false;
17562
17563 /*
17564 Indicates special case involving non-atomic ALTER TABLE which adds
17565 foreign keys and then fails at the late stage. Such ALTER TABLE still
17566 requires FK parent invalidation even despite of error.
17567 */
17568 79143 bool invalidate_fk_parents_on_error = false;
17569
17570 79143 dd::Encrypt_result old_er{false, false};
17571 79143 dd::Encrypt_result new_er{false, false};
17572
17573 /*
17574 If we are ALTERing non-temporary table in SE not supporting atomic DDL
17575 we don't have dd::Table object describing new version of table yet.
17576 Retrieve it now.
17577 */
17578 79143 dd::Table *table_def = non_dd_table_def.get();
17579
2/2
✓ Branch 0 taken 16095 times.
✓ Branch 1 taken 63048 times.
79143 if (!table_def) {
17580
4/8
✓ Branch 0 taken 16095 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16095 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16095 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 16095 times.
16095 if (thd->dd_client()->acquire_for_modification(
17581 alter_ctx.new_db, alter_ctx.tmp_name, &table_def))
17582 goto err_new_table_cleanup;
17583
17584
1/2
✓ Branch 0 taken 16095 times.
✗ Branch 1 not taken.
16095 set_check_constraints_alter_mode(table_def, alter_info);
17585
17586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16095 times.
16095 assert(table_def);
17587 }
17588
17589
2/2
✓ Branch 0 taken 77992 times.
✓ Branch 1 taken 1151 times.
79143 if (!is_tmp_table) {
17590 // Check for usage of prefix key index in PARTITION BY KEY() function.
17591
1/2
✓ Branch 0 taken 77992 times.
✗ Branch 1 not taken.
77992 dd::warn_on_deprecated_prefix_key_partition(
17592 thd, alter_ctx.db, alter_ctx.table_name, table_def, false);
17593 }
17594
17595
2/4
✓ Branch 0 taken 79143 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 79143 times.
79143 if (remove_secondary_engine(thd, *table_list, *create_info, old_table_def))
17596 goto err_new_table_cleanup;
17597
17598 // If we are changing the tablespace or the table encryption type.
17599
4/4
✓ Branch 0 taken 77992 times.
✓ Branch 1 taken 1151 times.
✓ Branch 2 taken 14420 times.
✓ Branch 3 taken 64723 times.
157135 if (old_table_def &&
17600
2/2
✓ Branch 0 taken 72834 times.
✓ Branch 1 taken 5158 times.
77992 (create_info->used_fields & HA_CREATE_USED_TABLESPACE ||
17601
2/2
✓ Branch 0 taken 68700 times.
✓ Branch 1 taken 4134 times.
72834 create_info->used_fields & HA_CREATE_USED_ENCRYPT ||
17602
4/4
✓ Branch 0 taken 63671 times.
✓ Branch 1 taken 5029 times.
✓ Branch 2 taken 99 times.
✓ Branch 3 taken 63572 times.
132371 create_info->used_fields & HA_CREATE_USED_AUTOEXTEND_SIZE ||
17603 63671 alter_ctx.is_database_changed())) {
17604 14420 bool source_is_general_tablespace{false};
17605 14420 bool source_encrytion_type{false};
17606 14420 bool destination_is_general_tablespace{false};
17607 14420 bool destination_encrytion_type{false};
17608
17609 // Determine source tablespace type and encryption type.
17610
1/2
✓ Branch 0 taken 14420 times.
✗ Branch 1 not taken.
14420 old_er = dd::is_tablespace_encrypted(thd, *old_table_def,
17611 &source_is_general_tablespace);
17612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14420 times.
14420 if (old_er.error) {
17613 61 goto err_new_table_cleanup;
17614 }
17615 14420 source_encrytion_type = old_er.value;
17616
2/2
✓ Branch 0 taken 9315 times.
✓ Branch 1 taken 5105 times.
23735 if (!source_is_general_tablespace &&
17617
9/14
✓ Branch 0 taken 9315 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9315 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9315 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9297 times.
✓ Branch 7 taken 18 times.
✓ Branch 8 taken 9315 times.
✓ Branch 9 taken 5105 times.
✓ Branch 10 taken 9297 times.
✓ Branch 11 taken 5123 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
23735 old_table_def->options().exists("encrypt_type")) {
17618 9297 dd::String_type et;
17619
3/6
✓ Branch 0 taken 9297 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9297 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9297 times.
✗ Branch 5 not taken.
9297 (void)old_table_def->options().get("encrypt_type", &et);
17620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9297 times.
9297 assert(et.empty() == false);
17621
1/2
✓ Branch 0 taken 9297 times.
✗ Branch 1 not taken.
9297 source_encrytion_type = is_encrypted(et);
17622 9297 }
17623
17624 // Determine destination tablespace type and encryption type.
17625
1/2
✓ Branch 0 taken 14420 times.
✗ Branch 1 not taken.
14420 new_er = dd::is_tablespace_encrypted(thd, *table_def,
17626 &destination_is_general_tablespace);
17627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14420 times.
14420 if (new_er.error) {
17628 goto err_new_table_cleanup;
17629 }
17630 14420 destination_encrytion_type = new_er.value;
17631
2/2
✓ Branch 0 taken 7521 times.
✓ Branch 1 taken 6899 times.
21941 if (!destination_is_general_tablespace &&
17632
9/14
✓ Branch 0 taken 7521 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7521 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7521 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7505 times.
✓ Branch 7 taken 16 times.
✓ Branch 8 taken 7521 times.
✓ Branch 9 taken 6899 times.
✓ Branch 10 taken 7505 times.
✓ Branch 11 taken 6915 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
21941 table_def->options().exists("encrypt_type")) {
17633 7505 dd::String_type et;
17634
3/6
✓ Branch 0 taken 7505 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7505 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7505 times.
✗ Branch 5 not taken.
7505 (void)table_def->options().get("encrypt_type", &et);
17635
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7505 times.
7505 assert(et.empty() == false);
17636
1/2
✓ Branch 0 taken 7505 times.
✗ Branch 1 not taken.
7505 destination_encrytion_type = is_encrypted(et);
17637 7505 }
17638
17639 /*
17640 Disallow converting a general tablespace to a file-per-table
17641 tablespace without a explicit ENCRYPTION clause.
17642 */
17643
4/4
✓ Branch 0 taken 5105 times.
✓ Branch 1 taken 9315 times.
✓ Branch 2 taken 331 times.
✓ Branch 3 taken 4774 times.
14420 if (source_is_general_tablespace && source_encrytion_type == true &&
17644
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 242 times.
331 !destination_is_general_tablespace &&
17645
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 83 times.
89 !(create_info->used_fields & HA_CREATE_USED_ENCRYPT)) {
17646
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(ER_TARGET_TABLESPACE_UNENCRYPTED, MYF(0));
17647 6 goto err_new_table_cleanup;
17648 }
17649
17650 /*
17651 Disallow moving encrypted table (using general or file-per-table
17652 tablespace) to a unencrypted general tablespace.
17653 */
17654
4/4
✓ Branch 0 taken 624 times.
✓ Branch 1 taken 13790 times.
✓ Branch 2 taken 305 times.
✓ Branch 3 taken 319 times.
14414 if (source_encrytion_type && destination_is_general_tablespace &&
17655
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 250 times.
305 !destination_encrytion_type) {
17656
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 my_error(ER_TARGET_TABLESPACE_UNENCRYPTED, MYF(0));
17657 55 goto err_new_table_cleanup;
17658 }
17659
17660 /*
17661 Check table encryption privilege, if table encryption type differ
17662 from schema encryption type.
17663 */
17664
3/4
✓ Branch 0 taken 14359 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 643 times.
✓ Branch 3 taken 13716 times.
14359 if (new_schema->default_encryption() != destination_encrytion_type) {
17665 // Ignore privilege check and show warning if database is same and
17666 // table encryption type is not changed.
17667
4/4
✓ Branch 0 taken 595 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 312 times.
✓ Branch 3 taken 283 times.
643 bool show_warning = !alter_ctx.is_database_changed() &&
17668 643 source_encrytion_type == destination_encrytion_type;
17669
17670
4/4
✓ Branch 0 taken 331 times.
✓ Branch 1 taken 312 times.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 219 times.
643 if (!show_warning && opt_table_encryption_privilege_check) {
17671
3/4
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 58 times.
112 if (check_table_encryption_admin_access(thd)) {
17672
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 my_error(ER_CANNOT_SET_TABLE_ENCRYPTION, MYF(0));
17673 54 return true;
17674 }
17675
5/6
✓ Branch 0 taken 531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 455 times.
✓ Branch 4 taken 76 times.
✓ Branch 5 taken 455 times.
607 } else if (new_schema->default_encryption() &&
17676
1/2
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
76 !destination_encrytion_type) {
17677
2/4
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
✗ Branch 3 not taken.
76 push_warning(thd, Sql_condition::SL_WARNING,
17678 WARN_UNENCRYPTED_TABLE_IN_ENCRYPTED_DB,
17679 ER_THD(thd, WARN_UNENCRYPTED_TABLE_IN_ENCRYPTED_DB));
17680 }
17681 }
17682 }
17683
17684
2/2
✓ Branch 0 taken 77877 times.
✓ Branch 1 taken 1151 times.
79028 if (old_table_def) {
17685
3/4
✓ Branch 0 taken 77877 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1325 times.
✓ Branch 3 taken 76552 times.
77877 if (is_checked_for_upgrade(*old_table_def)) {
17686
3/16
✓ Branch 0 taken 1325 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1325 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1325 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
1325 DBUG_PRINT("admin", ("Transfering upgrade mark "
17687 "from Table %s (%llu) to Table %s (%llu)",
17688 old_table_def->name().c_str(), old_table_def->id(),
17689 table_def->name().c_str(), table_def->id()));
17690
1/2
✓ Branch 0 taken 1325 times.
✗ Branch 1 not taken.
1325 table_def->mark_as_checked_for_upgrade();
17691 }
17692 }
17693
17694 /*
17695 Check if new table definition is compatible with foreign keys
17696 on other tales which reference this one. We want to do this
17697 before starting potentially expensive main phases of COPYing
17698 or INPLACE ALTER TABLE.
17699 */
17700
2/2
✓ Branch 0 taken 77877 times.
✓ Branch 1 taken 1151 times.
79028 if (!is_tmp_table) {
17701
2/2
✓ Branch 0 taken 815 times.
✓ Branch 1 taken 77062 times.
77877 if (new_db_type != old_db_type) {
17702 /*
17703 By changing table's storage engine we might be introducing parent
17704 table for previously orphan foreign keys in the new SE. We need
17705 to lock child tables of such orphan foreign keys. OTOH it is safe
17706 to assume that if SE is changed table can't be parent in any
17707 foreign keys in old SE.
17708
17709 We assume that ALTER TABLE which combines change of SE and renaming
17710 of table is executed by changing SE first and then performing rename
17711 (this is closer to ALTER TABLE real implementation). So such ALTER
17712 TABLEs need to pick up orphan foreign keys associated with old table
17713 names as well. Thus we use old table name in the below check.
17714 */
17715
2/4
✓ Branch 0 taken 815 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 815 times.
815 assert(old_table_def->foreign_key_parents().size() == 0);
17716
17717
3/4
✓ Branch 0 taken 815 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 811 times.
815 if (check_fk_children_after_parent_def_change(
17718 thd, table_list->db, table_list->table_name, nullptr, nullptr,
17719 new_db_type, table_def))
17720 4 goto err_new_table_cleanup;
17721 } else {
17722
3/4
✓ Branch 0 taken 77062 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 77052 times.
77062 if (check_fk_children_after_parent_def_change(
17723 thd, table_list->db, table_list->table_name, new_db_type,
17724 old_table_def, table_def, alter_info))
17725 10 goto err_new_table_cleanup;
17726 }
17727
17728
4/4
✓ Branch 0 taken 278 times.
✓ Branch 1 taken 77585 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 77861 times.
78141 if (alter_ctx.is_table_renamed() &&
17729
3/4
✓ Branch 0 taken 278 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 276 times.
278 check_fk_children_after_parent_def_change(
17730 thd, alter_ctx.new_db, alter_ctx.new_alias, table_list->db,
17731 table_list->table_name, new_db_type, table_def))
17732 2 goto err_new_table_cleanup;
17733 }
17734
17735
2/2
✓ Branch 0 taken 74915 times.
✓ Branch 1 taken 4097 times.
79012 if (alter_info->requested_algorithm !=
17736 Alter_info::ALTER_TABLE_ALGORITHM_COPY) {
17737 Alter_inplace_info ha_alter_info(create_info, alter_info,
17738 74915 alter_ctx.error_if_not_empty, key_info,
17739 74915 key_count, thd->work_part_info);
17740 74915 TABLE *altered_table = nullptr;
17741 74915 bool use_inplace = true;
17742
17743 /* Fill the Alter_inplace_info structure. */
17744
3/4
✓ Branch 0 taken 74915 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 74914 times.
74915 if (fill_alter_inplace_info(thd, table, &ha_alter_info))
17745 1 goto err_new_table_cleanup;
17746
17747
2/8
✓ Branch 0 taken 74914 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 74914 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
74914 DBUG_EXECUTE_IF("innodb_index_drop_count_zero", {
17748 if (ha_alter_info.index_drop_count) {
17749 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0), "Index rebuild",
17750 "Without rebuild");
17751 return true;
17752 }
17753 };);
17754
17755
2/8
✓ Branch 0 taken 74914 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 74914 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
74914 DBUG_EXECUTE_IF("innodb_index_drop_count_one", {
17756 if (ha_alter_info.index_drop_count != 1) {
17757 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0), "Index change",
17758 "Index rebuild");
17759 return true;
17760 }
17761 };);
17762
17763 // We assume that the table is non-temporary.
17764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74914 times.
74914 assert(!table->s->tmp_table);
17765
17766
3/4
✓ Branch 0 taken 74914 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 74894 times.
74914 if (!(altered_table = open_table_uncached(
17767 thd, alter_ctx.get_tmp_path(), alter_ctx.new_db,
17768 alter_ctx.tmp_name, true, false, *table_def)))
17769 20 goto err_new_table_cleanup;
17770
17771
3/4
✓ Branch 0 taken 72919 times.
✓ Branch 1 taken 1975 times.
✓ Branch 2 taken 72919 times.
✗ Branch 3 not taken.
74894 DEBUG_SYNC(thd, "after_open_altered_table");
17772
17773 /* Set markers for fields in TABLE object for altered table. */
17774 74894 update_altered_table(ha_alter_info, altered_table);
17775
17776 /*
17777 Updating field definitions in 'altered_table' with zip_dict_name values
17778 from 'ha_alter_info.alter_info->create_list'
17779 */
17780
2/4
✓ Branch 0 taken 74894 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74894 times.
✗ Branch 3 not taken.
74894 if (ha_alter_info.alter_info != 0 && altered_table != 0) {
17781 74894 altered_table->update_compressed_columns_info(
17782
1/2
✓ Branch 0 taken 74894 times.
✗ Branch 1 not taken.
74894 ha_alter_info.alter_info->create_list);
17783 }
17784
17785 /*
17786 Mark all columns in 'altered_table' as used to allow usage
17787 of its record[0] buffer and Field objects during in-place
17788 ALTER TABLE.
17789 */
17790 74894 altered_table->column_bitmaps_set_no_signal(&altered_table->s->all_set,
17791 74894 &altered_table->s->all_set);
17792
17793
1/2
✓ Branch 0 taken 74894 times.
✗ Branch 1 not taken.
74894 set_column_static_defaults(altered_table, alter_info->create_list);
17794
17795
2/2
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 74660 times.
74894 if (ha_alter_info.handler_flags == 0) {
17796 /*
17797 No-op ALTER, no need to call handler API functions.
17798
17799 If this code path is entered for an ALTER statement that
17800 should not be a real no-op, new handler flags should be added
17801 and fill_alter_inplace_info() adjusted.
17802
17803 Note that we can end up here if an ALTER statement has clauses
17804 that cancel each other out (e.g. ADD/DROP identically index).
17805
17806 Also note that we ignore the LOCK clause here.
17807 */
17808
1/2
✓ Branch 0 taken 234 times.
✗ Branch 1 not taken.
234 close_temporary_table(thd, altered_table, true, false);
17809
17810
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 148 times.
234 if (!(create_info->db_type->flags & HTON_SUPPORTS_ATOMIC_DDL)) {
17811 // Delete temporary table object from data dictionary.
17812
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 bool result = dd::drop_table(thd, alter_ctx.new_db, alter_ctx.tmp_name,
17813 *table_def);
17814
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 (void)trans_intermediate_ddl_commit(thd, result);
17815 }
17816
17817 234 is_noop = true;
17818 234 goto end_inplace_noop;
17819 }
17820
17821 // Ask storage engine whether to use copy or in-place
17822 enum_alter_inplace_result inplace_supported =
17823
1/2
✓ Branch 0 taken 74660 times.
✗ Branch 1 not taken.
74660 table->file->check_if_supported_inplace_alter(altered_table,
17824 &ha_alter_info);
17825
17826 // If INSTANT was requested but it is not supported, report error.
17827
2/2
✓ Branch 0 taken 1007 times.
✓ Branch 1 taken 73653 times.
74660 if (alter_info->requested_algorithm ==
17828
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 949 times.
1007 Alter_info::ALTER_TABLE_ALGORITHM_INSTANT &&
17829
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 10 times.
58 inplace_supported != HA_ALTER_INPLACE_INSTANT &&
17830 inplace_supported != HA_ALTER_ERROR) {
17831
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 ha_alter_info.report_unsupported_error("ALGORITHM=INSTANT",
17832 "ALGORITHM=COPY/INPLACE");
17833
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 close_temporary_table(thd, altered_table, true, false);
17834 48 goto err_new_table_cleanup;
17835 }
17836
17837
5/5
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1955 times.
✓ Branch 2 taken 55820 times.
✓ Branch 3 taken 16809 times.
✓ Branch 4 taken 22 times.
74612 switch (inplace_supported) {
17838 6 case HA_ALTER_INPLACE_EXCLUSIVE_LOCK:
17839 // If SHARED lock and no particular algorithm was requested, use COPY.
17840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED &&
17841 alter_info->requested_algorithm ==
17842 Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT) {
17843 use_inplace = false;
17844 }
17845 // Otherwise, if weaker lock was requested, report error.
17846
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 else if (alter_info->requested_lock ==
17847 6 Alter_info::ALTER_TABLE_LOCK_NONE ||
17848
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 alter_info->requested_lock ==
17849 Alter_info::ALTER_TABLE_LOCK_SHARED) {
17850 ha_alter_info.report_unsupported_error("LOCK=NONE/SHARED",
17851 "LOCK=EXCLUSIVE");
17852 close_temporary_table(thd, altered_table, true, false);
17853 goto err_new_table_cleanup;
17854 }
17855 6 break;
17856 1955 case HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE:
17857 case HA_ALTER_INPLACE_SHARED_LOCK:
17858 // If weaker lock was requested, report error.
17859
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1944 times.
1955 if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_NONE) {
17860
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 ha_alter_info.report_unsupported_error("LOCK=NONE", "LOCK=SHARED");
17861
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 close_temporary_table(thd, altered_table, true, false);
17862 11 goto err_new_table_cleanup;
17863 }
17864 1944 break;
17865 55820 case HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE:
17866 case HA_ALTER_INPLACE_NO_LOCK:
17867 case HA_ALTER_INPLACE_INSTANT:
17868 /*
17869 Note that any instant operation is also in fact in-place operation.
17870
17871 It is totally safe to execute operation using instant algorithm if it
17872 has no drawbacks as compared to in-place algorithm even if user
17873 explicitly asked for ALGORITHM=INPLACE. Doing so, also allows to
17874 keep code in engines which support only limited subset of in-place
17875 ALTER TABLE operations as instant metadata only changes simple.
17876
17877 If instant algorithm has some downsides to in-place algorithm and user
17878 explicitly asks for ALGORITHM=INPLACE it is responsibility of storage
17879 engine to fallback to in-place algorithm execution by returning
17880 HA_ALTER_INPLACE_NO_LOCK or HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE.
17881 */
17882 55820 break;
17883 16809 case HA_ALTER_INPLACE_NOT_SUPPORTED:
17884 // If INPLACE was requested, report error.
17885
2/2
✓ Branch 0 taken 159 times.
✓ Branch 1 taken 16650 times.
16809 if (alter_info->requested_algorithm ==
17886 Alter_info::ALTER_TABLE_ALGORITHM_INPLACE) {
17887
1/2
✓ Branch 0 taken 159 times.
✗ Branch 1 not taken.
159 ha_alter_info.report_unsupported_error("ALGORITHM=INPLACE",
17888 "ALGORITHM=COPY");
17889
1/2
✓ Branch 0 taken 159 times.
✗ Branch 1 not taken.
159 close_temporary_table(thd, altered_table, true, false);
17890 159 goto err_new_table_cleanup;
17891 }
17892 // COPY with LOCK=NONE is not supported, no point in trying.
17893
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 16647 times.
16650 if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_NONE) {
17894
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ha_alter_info.report_unsupported_error("LOCK=NONE", "LOCK=SHARED");
17895
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 close_temporary_table(thd, altered_table, true, false);
17896 3 goto err_new_table_cleanup;
17897 }
17898 // Otherwise use COPY
17899 16647 use_inplace = false;
17900 16647 break;
17901 22 case HA_ALTER_ERROR:
17902 default:
17903
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 close_temporary_table(thd, altered_table, true, false);
17904 22 goto err_new_table_cleanup;
17905 }
17906
17907
2/2
✓ Branch 0 taken 57770 times.
✓ Branch 1 taken 16647 times.
74417 if (use_inplace) {
17908
3/4
✓ Branch 0 taken 57283 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 571 times.
✓ Branch 3 taken 56712 times.
57770 if (mysql_inplace_alter_table(thd, *schema, *new_schema, old_table_def,
17909 table_def, table_list, table, altered_table,
17910 &ha_alter_info, inplace_supported,
17911 &alter_ctx, columns, fk_key_info,
17912 fk_key_count, &fk_invalidator)) {
17913 571 return true;
17914 }
17915
17916 56712 const dd::Table *new_table_def = nullptr;
17917
4/8
✓ Branch 0 taken 56712 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56712 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 56712 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 56712 times.
56712 if (thd->dd_client()->acquire(alter_ctx.new_db, alter_ctx.new_name,
17918 &new_table_def)) {
17919 DBUG_LOG("zip_dict",
17920 "Acquiring dictionary table object failed "
17921 " for query "
17922 << thd->query().str << " table_db: " << alter_ctx.new_db
17923 << " table_name: " << alter_ctx.new_name);
17924 return true;
17925 }
17926 /* New table is successfully created, check if any columns have
17927 compression dictionary and add entry for them in
17928 mysql.compression_dictionary_cols table */
17929
2/4
✓ Branch 0 taken 56712 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 56712 times.
56712 if (compression_dict::cols_table_insert(thd, *new_table_def)) return true;
17930
17931 56712 goto end_inplace;
17932 } else {
17933
1/2
✓ Branch 0 taken 16647 times.
✗ Branch 1 not taken.
16647 close_temporary_table(thd, altered_table, true, false);
17934 }
17935
5/5
✓ Branch 0 taken 16647 times.
✓ Branch 1 taken 264 times.
✓ Branch 2 taken 571 times.
✓ Branch 3 taken 234 times.
✓ Branch 4 taken 56712 times.
74428 }
17936
17937 /* ALTER TABLE using copy algorithm. */
17938
17939 /* Check if ALTER TABLE is compatible with foreign key definitions. */
17940
3/4
✓ Branch 0 taken 20744 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 20742 times.
20744 if (fk_check_copy_alter_table(thd, table_list, old_table_def, alter_info))
17941 2 goto err_new_table_cleanup;
17942
17943
2/2
✓ Branch 0 taken 19591 times.
✓ Branch 1 taken 1151 times.
20742 if (!table->s->tmp_table) {
17944
1/2
✓ Branch 0 taken 19591 times.
✗ Branch 1 not taken.
19591 MDL_request_list mdl_requests;
17945
17946 // COPY algorithm doesn't work with concurrent writes.
17947
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 19584 times.
19591 if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_NONE) {
17948
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0), "LOCK=NONE",
17949 ER_THD(thd, ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COPY),
17950 "LOCK=SHARED");
17951 34 goto err_new_table_cleanup;
17952 }
17953
17954 // If EXCLUSIVE lock is requested, upgrade already.
17955
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 19572 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19584 times.
19596 if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE &&
17956
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
17957 goto err_new_table_cleanup;
17958
17959 /*
17960 Otherwise upgrade to SHARED_NO_WRITE.
17961 Note that under LOCK TABLES, we will already have SHARED_NO_READ_WRITE.
17962 */
17963
4/4
✓ Branch 0 taken 19572 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 19558 times.
39156 if (alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE &&
17964
3/4
✓ Branch 0 taken 19572 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 19546 times.
19572 thd->mdl_context.upgrade_shared_lock(mdl_ticket, MDL_SHARED_NO_WRITE,
17965 thd->variables.lock_wait_timeout))
17966 26 goto err_new_table_cleanup;
17967
17968
3/4
✓ Branch 0 taken 19365 times.
✓ Branch 1 taken 193 times.
✓ Branch 2 taken 19365 times.
✗ Branch 3 not taken.
19558 DEBUG_SYNC(thd, "alter_table_copy_after_lock_upgrade");
17969
17970 /*
17971 COPY algorithm creates new table version in the new database.
17972 So if new database differs from old one we need to lock all
17973 foreign key names in new table version. If it is the same as
17974 the old one we need to lock only names of foreign keys added.
17975
17976 Also if table is renamed we need to acquire locks on all foreign
17977 key names involved (taking into account adjustment of auto-generated
17978 names).
17979 */
17980
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 19516 times.
19558 if (alter_ctx.is_database_changed()) {
17981
2/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 42 times.
42 if (collect_fk_names(thd, alter_ctx.new_db, table_def, &mdl_requests))
17982 goto err_new_table_cleanup;
17983 } else {
17984
3/6
✓ Branch 0 taken 19516 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19516 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 19516 times.
19516 if (collect_fk_names_for_new_fks(
17985 thd, alter_ctx.new_db, table_list->table_name, alter_info,
17986 new_db_type,
17987 get_fk_max_generated_name_number(table_list->table_name,
17988 old_table_def, new_db_type),
17989 &mdl_requests))
17990 goto err_new_table_cleanup;
17991 }
17992
17993
3/4
✓ Branch 0 taken 113 times.
✓ Branch 1 taken 19445 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19558 times.
19671 if (alter_ctx.is_table_renamed() &&
17994
2/4
✓ Branch 0 taken 113 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 113 times.
113 collect_fk_names_for_rename_table(
17995 thd, table_list->db, table_list->table_name, table_def, new_db_type,
17996 alter_ctx.new_db, alter_ctx.new_name, &mdl_requests))
17997 goto err_new_table_cleanup;
17998
17999 /*
18000 Acquire SRO locks on parent tables for newly added foreign keys
18001 in order to prevent concurrent DML on them.
18002
18003 This is temporary workaround to the problem caused by the fact that
18004 InnoDB makes such foreign keys visible in its internal dictionary
18005 cache before ALTER TABLE commit. So such DML can result in access
18006 to our temporary table without prior acquisition of metadata lock
18007 on it (which would have blocked such access normally). As result
18008 our ALTER TABLE can fail due to locks acquired by these accesses.
18009
18010 Long-term the problem should be solved by adjusting InnoDB code
18011 to avoid making such uncommitted changes visible to other
18012 connections.
18013 */
18014
2/4
✓ Branch 0 taken 19558 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19558 times.
19558 if (collect_fk_parents_for_new_fks(
18015 thd, table_list->db, table_list->table_name, alter_info,
18016 MDL_SHARED_READ_ONLY, nullptr, &mdl_requests, nullptr))
18017 goto err_new_table_cleanup;
18018
18019
3/4
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 19457 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19558 times.
19659 if (!mdl_requests.is_empty() &&
18020
2/4
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 101 times.
101 thd->mdl_context.acquire_locks(&mdl_requests,
18021 thd->variables.lock_wait_timeout))
18022 goto err_new_table_cleanup;
18023
18024 /*
18025 Check if ALTER TABLE results in any foreign key name conflicts
18026 before starting potentially expensive copying operation.
18027 */
18028
4/10
✓ Branch 0 taken 19558 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19558 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7152 times.
✓ Branch 5 taken 12406 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
39116 if (!dd::get_dictionary()->is_dd_table_name(table_list->db,
18029
6/10
✓ Branch 0 taken 19558 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19558 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19558 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 19556 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 19558 times.
✗ Branch 9 not taken.
58672 table_list->table_name) &&
18030
2/2
✓ Branch 0 taken 7152 times.
✓ Branch 1 taken 12404 times.
19556 (new_db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS)) {
18031
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 7111 times.
7152 if (alter_ctx.is_database_changed()) {
18032 /*
18033 If new table version was created schema different from the old one
18034 we need to check names for both pre-existing and newly added foreign
18035 keys.
18036 */
18037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 for (FOREIGN_KEY *fk = fk_key_info; fk < fk_key_info + fk_key_count;
18038 ++fk) {
18039 bool exists;
18040 if (thd->dd_client()->check_foreign_key_exists(*new_schema, fk->name,
18041 &exists))
18042 goto err_new_table_cleanup;
18043
18044 if (exists) {
18045 my_error(ER_FK_DUP_NAME, MYF(0), fk->name);
18046 goto err_new_table_cleanup;
18047 }
18048 }
18049 } else {
18050 /* Otherwise we can limit our check to newly added foreign keys only. */
18051 7201 for (FOREIGN_KEY *fk = fk_key_info + alter_ctx.fk_count;
18052
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 7110 times.
7201 fk < fk_key_info + fk_key_count; ++fk) {
18053 bool exists;
18054
3/6
✓ Branch 0 taken 91 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 91 times.
91 if (thd->dd_client()->check_foreign_key_exists(*new_schema, fk->name,
18055 &exists))
18056 1 goto err_new_table_cleanup;
18057
18058
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 90 times.
91 if (exists) {
18059
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_FK_DUP_NAME, MYF(0), fk->name);
18060 1 goto err_new_table_cleanup;
18061 }
18062 }
18063 }
18064
18065
3/4
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 7044 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7151 times.
7258 if (alter_ctx.is_table_renamed() &&
18066
2/4
✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 107 times.
107 check_fk_names_before_rename(thd, table_list, *table_def, new_db_type,
18067 *new_schema, alter_ctx))
18068 goto err_new_table_cleanup;
18069 }
18070 }
18071
18072 {
18073
3/4
✓ Branch 0 taken 20645 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 150 times.
✓ Branch 3 taken 20495 times.
20708 if (ha_create_table(thd, alter_ctx.get_tmp_path(), alter_ctx.new_db,
18074 alter_ctx.tmp_name, create_info,
18075 20708 &alter_info->create_list, false, true, table_def))
18076 150 goto err_new_table_cleanup;
18077
18078 /* Mark that we have created table in storage engine. */
18079 20495 no_ha_table = false;
18080
18081
2/2
✓ Branch 0 taken 1143 times.
✓ Branch 1 taken 19352 times.
20495 if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
18082
3/6
✓ Branch 0 taken 1143 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1143 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1143 times.
2286 if (thd->decide_logging_format(table_list) ||
18083
2/4
✓ Branch 0 taken 1143 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1143 times.
1143 !open_table_uncached(thd, alter_ctx.get_tmp_path(), alter_ctx.new_db,
18084 alter_ctx.tmp_name, true, true, *table_def))
18085 goto err_new_table_cleanup;
18086 /* in case of alter temp table send the tracker in OK packet */
18087
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1141 times.
1143 if (thd->session_tracker.get_tracker(SESSION_STATE_CHANGE_TRACKER)
18088
1/2
✓ Branch 0 taken 1143 times.
✗ Branch 1 not taken.
1143 ->is_enabled())
18089
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 thd->session_tracker.get_tracker(SESSION_STATE_CHANGE_TRACKER)
18090
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 ->mark_as_changed(thd, {});
18091 }
18092
18093 /* Open the table since we need to copy the data. */
18094
2/2
✓ Branch 0 taken 1143 times.
✓ Branch 1 taken 19352 times.
20495 if (table->s->tmp_table != NO_TMP_TABLE) {
18095
1/2
✓ Branch 0 taken 1143 times.
✗ Branch 1 not taken.
1143 TABLE_LIST tbl(alter_ctx.new_db, alter_ctx.tmp_name, TL_READ_NO_INSERT);
18096 /* Table is in thd->temporary_tables */
18097
1/2
✓ Branch 0 taken 1143 times.
✗ Branch 1 not taken.
1143 (void)open_temporary_table(thd, &tbl);
18098 1143 new_table = tbl.table;
18099 /* Transfer dd::Table ownership to temporary table's share. */
18100 1143 new_table->s->tmp_table_def = non_dd_table_def.release();
18101 } else {
18102 /* table is a normal table: Create temporary table in same directory */
18103 /* Open our intermediate table. */
18104 new_table =
18105
1/2
✓ Branch 0 taken 19352 times.
✗ Branch 1 not taken.
19352 open_table_uncached(thd, alter_ctx.get_tmp_path(), alter_ctx.new_db,
18106 alter_ctx.tmp_name, true, true, *table_def);
18107 }
18108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20495 times.
20495 if (!new_table) goto err_new_table_cleanup;
18109 /*
18110 Note: In case of MERGE table, we do not attach children. We do not
18111 copy data for MERGE tables. Only the children have data.
18112 */
18113
18114 // It's now safe to take the table level lock.
18115
2/4
✓ Branch 0 taken 20495 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 20495 times.
20495 if (lock_tables(thd, table_list, alter_ctx.tables_opened, 0))
18116 goto err_new_table_cleanup;
18117 }
18118
18119 /*
18120 We do not copy data for MERGE tables. Only the children have data.
18121 MERGE tables have HA_NO_COPY_ON_ALTER set.
18122 */
18123
2/2
✓ Branch 0 taken 20472 times.
✓ Branch 1 taken 23 times.
20495 if (!(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER)) {
18124 /*
18125 Check if we can temporarily remove secondary indexes from the table
18126 before copying the data and recreate them later to utilize InnoDB fast
18127 index creation.
18128 TODO: is there a better way to check for InnoDB?
18129 */
18130 const bool optimize_keys =
18131
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 20467 times.
20477 (alter_info->delayed_key_count > 0) &&
18132
3/6
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
5 !my_strcasecmp(system_charset_info, new_table->file->table_type(),
18133 "InnoDB");
18134 20472 new_table->next_number_field = new_table->found_next_number_field;
18135
1/2
✓ Branch 0 taken 20472 times.
✗ Branch 1 not taken.
20472 THD_STAGE_INFO(thd, stage_copy_to_tmp_table);
18136
4/6
✓ Branch 0 taken 20472 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 20471 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
21445 DBUG_EXECUTE_IF("abort_copy_table", {
18137 my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
18138 goto err_new_table_cleanup;
18139 });
18140
18141 /* List of dd::Indexes (secondary non-unique) in table_def that are marked
18142 as hidden. These indexes are temporarily disabled */
18143 20471 std::vector<dd::Index *> dd_disabled_sec_keys;
18144 20471 bool err_remove_keys = false;
18145
18146
1/2
✓ Branch 0 taken 20471 times.
✗ Branch 1 not taken.
20471 new_table->file->ha_extra(HA_EXTRA_BEGIN_ALTER_COPY);
18147
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 20466 times.
20471 if (optimize_keys) {
18148
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
10 err_remove_keys = remove_secondary_keys(
18149 thd, create_info, new_table, alter_info,
18150 5 is_tmp_table ? table->s->tmp_table_def : old_table_def, table_def,
18151 &dd_disabled_sec_keys);
18152 }
18153
18154 40940 bool err_copy = copy_data_between_tables(
18155 thd, thd->m_stage_progress_psi, table, new_table,
18156
1/2
✓ Branch 0 taken 20469 times.
✗ Branch 1 not taken.
20471 alter_info->create_list, &copied, &deleted, alter_info->keys_onoff,
18157 20469 &alter_ctx, optimize_keys);
18158
18159 20469 bool err_restore_keys = false;
18160
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 20464 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
20469 if (optimize_keys && !err_remove_keys) {
18161 // Use a clean diagnostic area so restore_secondary_keys can be executed
18162 // whatever the previous results
18163
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 auto da_man = thd->is_error()
18164 ? std::make_optional<Diagnostics_area_man>(thd)
18165
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 : std::nullopt;
18166
18167 err_restore_keys =
18168
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
5 restore_secondary_keys(thd, create_info, new_table, alter_info,
18169 table_def, &dd_disabled_sec_keys);
18170 4 }
18171
18172
1/2
✓ Branch 0 taken 20468 times.
✗ Branch 1 not taken.
20468 new_table->file->ha_extra(HA_EXTRA_END_ALTER_COPY);
18173
18174
3/4
✓ Branch 0 taken 19495 times.
✓ Branch 1 taken 973 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19495 times.
20468 if (err_copy || err_restore_keys) {
18175 973 goto err_new_table_cleanup;
18176 }
18177
18178
3/4
✓ Branch 0 taken 19302 times.
✓ Branch 1 taken 193 times.
✓ Branch 2 taken 19302 times.
✗ Branch 3 not taken.
19495 DEBUG_SYNC(thd, "alter_after_copy_table");
18179
2/2
✓ Branch 0 taken 19495 times.
✓ Branch 1 taken 973 times.
20468 } else {
18180 /* Should be MERGE only */
18181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 assert(new_table->file->ht->db_type == DB_TYPE_MRG_MYISAM);
18182
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 22 times.
31 if (!table->s->tmp_table &&
18183
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
8 wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
18184 1 goto err_new_table_cleanup;
18185
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 THD_STAGE_INFO(thd, stage_manage_keys);
18186
2/4
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
22 DEBUG_SYNC(thd, "alter_table_manage_keys");
18187
2/4
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
22 alter_table_manage_keys(thd, table, table->file->indexes_are_disabled(),
18188 alter_info->keys_onoff);
18189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 assert(!(new_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL));
18190
18191 /* Prevent intermediate commits to invoke commit order */
18192 Implicit_substatement_state_guard substatement_guard(
18193 thd, enum_implicit_substatement_guard_mode ::
18194
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 DISABLE_GTID_AND_SPCO_IF_SPCO_ACTIVE);
18195
18196
5/10
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 22 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 22 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 22 times.
22 if (trans_commit_stmt(thd) || trans_commit_implicit(thd))
18197 goto err_new_table_cleanup;
18198
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 }
18199
18200
2/2
✓ Branch 0 taken 1141 times.
✓ Branch 1 taken 18376 times.
19517 if (table->s->tmp_table != NO_TMP_TABLE) {
18201 /* Close lock if this is a transactional table */
18202
1/2
✓ Branch 0 taken 1141 times.
✗ Branch 1 not taken.
1141 if (thd->lock) {
18203
2/2
✓ Branch 0 taken 1140 times.
✓ Branch 1 taken 1 times.
1141 if (thd->locked_tables_mode != LTM_LOCK_TABLES &&
18204
1/2
✓ Branch 0 taken 1140 times.
✗ Branch 1 not taken.
1140 thd->locked_tables_mode != LTM_PRELOCKED_UNDER_LOCK_TABLES) {
18205
1/2
✓ Branch 0 taken 1140 times.
✗ Branch 1 not taken.
1140 mysql_unlock_tables(thd, thd->lock);
18206 1140 thd->lock = nullptr;
18207 } else {
18208 /*
18209 If LOCK TABLES list is not empty and contains this table,
18210 unlock the table and remove the table from this list.
18211 */
18212
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 mysql_lock_remove(thd, thd->lock, table);
18213 }
18214 }
18215 /* Remove link to old table and rename the new one */
18216
1/2
✓ Branch 0 taken 1141 times.
✗ Branch 1 not taken.
1141 close_temporary_table(thd, table, true, true);
18217 /* Should pass the 'new_name' as we store table name in the cache */
18218
2/4
✓ Branch 0 taken 1141 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1141 times.
1141 if (rename_temporary_table(thd, new_table, alter_ctx.new_db,
18219 alter_ctx.new_name))
18220 goto err_new_table_cleanup;
18221 /*
18222 We don't replicate alter table statement on temporary tables
18223 in RBR mode.
18224 */
18225
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 1113 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1141 times.
1169 if (!thd->is_current_stmt_binlog_format_row() &&
18226
4/8
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 28 times.
28 write_bin_log(thd, true, thd->query().str, thd->query().length)) {
18227 /*
18228 We can't revert replacement of old table version with a new one
18229 at this point. So, if possible, commit the statement to avoid
18230 new table version being emptied by statement rollback.
18231 */
18232 if (!thd->transaction_rollback_request) {
18233 (void)trans_commit_stmt(thd);
18234 (void)trans_commit_implicit(thd);
18235 }
18236 return true;
18237 }
18238
18239 // Do implicit commit for consistency with non-temporary table case/
18240
5/10
✓ Branch 0 taken 1141 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1141 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1141 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1141 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1141 times.
1141 if (trans_commit_stmt(thd) || trans_commit_implicit(thd)) return true;
18241
18242 1141 goto end_temporary;
18243 }
18244
18245 /*
18246 Close the intermediate table that will be the new table, but do
18247 not delete it! Even though MERGE tables do not have their children
18248 attached here it is safe to call close_temporary_table().
18249 */
18250
1/2
✓ Branch 0 taken 18376 times.
✗ Branch 1 not taken.
18376 close_temporary_table(thd, new_table, true, false);
18251 18376 new_table = nullptr;
18252
18253
3/4
✓ Branch 0 taken 18183 times.
✓ Branch 1 taken 193 times.
✓ Branch 2 taken 18183 times.
✗ Branch 3 not taken.
18376 DEBUG_SYNC(thd, "alter_table_before_rename_result_table");
18254
4/6
✓ Branch 0 taken 18376 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 18375 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
18376 DBUG_EXECUTE_IF("exit_after_alter_table_before_rename", {
18255 my_error(ER_UNKNOWN_ERROR, MYF(0));
18256 return true;
18257 });
18258
18259 /*
18260 Data is copied. Now we:
18261 1) Wait until all other threads will stop using old version of table
18262 by upgrading shared metadata lock to exclusive one.
18263 2) Close instances of table open by this thread and replace them
18264 with placeholders to simplify reopen process.
18265 3) Rename the old table to a temp name, rename the new one to the
18266 old name.
18267 4) If we are under LOCK TABLES and don't do ALTER TABLE ... RENAME
18268 we reopen new version of table.
18269 5) Write statement to the binary log.
18270 6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we
18271 remove placeholders and release metadata locks.
18272 7) If we are not not under LOCK TABLES we rely on the caller
18273 (mysql_execute_command()) to release metadata locks.
18274 */
18275
18276
1/2
✓ Branch 0 taken 18375 times.
✗ Branch 1 not taken.
18375 THD_STAGE_INFO(thd, stage_rename_result_table);
18277
18278
3/4
✓ Branch 0 taken 18375 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 18373 times.
18375 if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
18279 2 goto err_new_table_cleanup;
18280
18281
2/4
✓ Branch 0 taken 18373 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18373 times.
18373 if (collect_and_lock_fk_tables_for_complex_alter_table(
18282 thd, table_list, old_table_def, &alter_ctx, alter_info, old_db_type,
18283 new_db_type, &fk_invalidator))
18284 goto err_new_table_cleanup;
18285
18286 /*
18287 To ensure DDL atomicity after this point support from both old and
18288 new engines is necessary. If either of them lacks such support let
18289 us commit transaction so changes to data-dictionary are more closely
18290 reflect situations in SEs.
18291
18292 Also if new SE supports atomic DDL then we have not stored new table
18293 definition in on-disk data-dictionary so far. It is time to do this
18294 now if ALTER TABLE as a whole won't be atomic.
18295 */
18296
2/2
✓ Branch 0 taken 12143 times.
✓ Branch 1 taken 6230 times.
18373 if (!atomic_replace) {
18297
3/4
✓ Branch 0 taken 684 times.
✓ Branch 1 taken 11459 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12143 times.
12827 if ((new_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) &&
18298
2/4
✓ Branch 0 taken 684 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 684 times.
684 thd->dd_client()->store(non_dd_table_def.get()))
18299 goto err_new_table_cleanup;
18300
18301 /* Prevent intermediate commits to invoke commit order */
18302
1/2
✓ Branch 0 taken 12143 times.
✗ Branch 1 not taken.
12143 Implicit_substatement_state_guard substatement_guard(thd);
18303
18304
5/10
✓ Branch 0 taken 12143 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12143 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12143 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 12143 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 12143 times.
12143 if (trans_commit_stmt(thd) || trans_commit_implicit(thd))
18305 goto err_new_table_cleanup;
18306
18307 // Safety, in-memory dd::Table is no longer totally correct.
18308 12143 non_dd_table_def.reset();
18309
1/2
✓ Branch 0 taken 12143 times.
✗ Branch 1 not taken.
12143 }
18310
18311 char backup_name[32];
18312 assert(sizeof(my_thread_id) == 4);
18313 18373 snprintf(backup_name, sizeof(backup_name), "%s2-%lx-%x", tmp_file_prefix,
18314 current_pid, thd->thread_id());
18315
3/4
✓ Branch 0 taken 687 times.
✓ Branch 1 taken 17686 times.
✓ Branch 2 taken 687 times.
✗ Branch 3 not taken.
18373 if (lower_case_table_names) my_casedn_str(files_charset_info, backup_name);
18316
18317
1/2
✓ Branch 0 taken 18373 times.
✗ Branch 1 not taken.
18373 close_all_tables_for_name(thd, table->s, false, nullptr);
18318 18373 table_list->table = table = nullptr; /* Safety */
18319
18320 /*
18321 Rename the old version to temporary name to have a backup in case
18322 anything goes wrong while renaming the new table.
18323
18324 Take the X metadata lock on this temporary name too. This ensures that
18325 concurrent I_S queries won't try to open it. Assert to ensure we do not
18326 come here when ALTERing temporary table.
18327 */
18328 {
18329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18373 times.
18373 assert(!is_tmp_table);
18330 18373 MDL_request backup_name_mdl_request;
18331
1/2
✓ Branch 0 taken 18373 times.
✗ Branch 1 not taken.
18373 MDL_REQUEST_INIT(&backup_name_mdl_request, MDL_key::TABLE, alter_ctx.db,
18332 backup_name, MDL_EXCLUSIVE, MDL_STATEMENT);
18333
1/2
✓ Branch 0 taken 18373 times.
✗ Branch 1 not taken.
18373 dd::cache::Dictionary_client::Auto_releaser releaser_2(thd->dd_client());
18334 18373 const dd::Table *backup_table = nullptr;
18335
18336 55119 if (thd->mdl_context.acquire_lock(&backup_name_mdl_request,
18337
2/4
✓ Branch 0 taken 18373 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18373 times.
✗ Branch 3 not taken.
36746 thd->variables.lock_wait_timeout) ||
18338
7/18
✓ Branch 0 taken 18373 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18373 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18373 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 18373 times.
✓ Branch 8 taken 18373 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 18373 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 18373 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
36746 thd->dd_client()->acquire(alter_ctx.db, backup_name, &backup_table)) {
18339 /* purecov: begin tested */
18340 /*
18341 We need to clear THD::transaction_rollback_request (which might
18342 be set due to MDL deadlock) before attempting to remove new version
18343 of table.
18344 */
18345 if (thd->transaction_rollback_request) {
18346 trans_rollback_stmt(thd);
18347 trans_rollback(thd);
18348 }
18349
18350 if (!atomic_replace) {
18351 (void)quick_rm_table(thd, new_db_type, alter_ctx.new_db,
18352 alter_ctx.tmp_name, FN_IS_TMP);
18353 }
18354 goto err_with_mdl;
18355 /* purecov: end */
18356 }
18357
18358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18373 times.
18373 if (backup_table != nullptr) {
18359 /* purecov: begin tested */
18360 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), backup_name);
18361
18362 if (!atomic_replace) {
18363 (void)quick_rm_table(thd, new_db_type, alter_ctx.new_db,
18364 alter_ctx.tmp_name, FN_IS_TMP);
18365 }
18366 goto err_with_mdl;
18367 /* purecov: end */
18368 }
18369
1/2
✓ Branch 0 taken 18373 times.
✗ Branch 1 not taken.
18373 }
18370
18371
5/6
✓ Branch 0 taken 6230 times.
✓ Branch 1 taken 12143 times.
✓ Branch 2 taken 18358 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 18353 times.
18373 if (mysql_rename_table(thd, old_db_type, alter_ctx.db, alter_ctx.table_name,
18372 alter_ctx.db, alter_ctx.table_name, *schema,
18373 alter_ctx.db, backup_name,
18374 FN_TO_IS_TMP | (atomic_replace ? NO_DD_COMMIT : 0) |
18375 NO_FK_RENAME | NO_CC_RENAME)) {
18376 // Rename to temporary name failed, delete the new table, abort ALTER.
18377
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (!atomic_replace) {
18378 /*
18379 In non-atomic mode situations when the SE has requested rollback
18380 should be handled already, by executing rollback right inside
18381 mysql_rename_table() call.
18382 */
18383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 assert(!thd->transaction_rollback_request);
18384
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 (void)quick_rm_table(thd, new_db_type, alter_ctx.new_db,
18385 alter_ctx.tmp_name, FN_IS_TMP);
18386 }
18387 5 goto err_with_mdl;
18388 }
18389
18390 /*
18391 The below code assumes that only SE capable of atomic DDL support FK.
18392 This is somewhat simplifies error handling below.
18393
18394 Note that we need to handle FKs atomically with this rename in order
18395 to handle scenario when, for example, MyISAM table is altered to InnoDB
18396 SE and some FKs are added at the same time.
18397 */
18398
3/4
✓ Branch 0 taken 6899 times.
✓ Branch 1 taken 11454 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6899 times.
18353 assert(!(new_db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS) ||
18399 (new_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL));
18400
18401 /*
18402 We also assume that we can't have non-atomic ALTER TABLE which
18403 will preserve any foreign keys (i.e. such ALTER TABLE can only
18404 drop all foreign keys on the table, or add new foreign keys to
18405 table which previously didn't have any).
18406 */
18407
3/4
✓ Branch 0 taken 12138 times.
✓ Branch 1 taken 6215 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12138 times.
18353 assert(atomic_replace || alter_ctx.fk_count == 0);
18408
18409 /*
18410 If both old and new SEs support atomic DDL then we have not stored
18411 new table definition in on-disk data-dictionary so far. It is time
18412 to do this now. However, before doing this we need to rename foreign
18413 keys in old table definition to temporary names to avoid conflicts
18414 with duplicate names.
18415 */
18416
2/2
✓ Branch 0 taken 6215 times.
✓ Branch 1 taken 12138 times.
18353 if (atomic_replace) {
18417
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 6167 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6215 times.
6263 if (alter_ctx.fk_count > 0 &&
18418
2/4
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
48 adjust_foreign_key_names_for_old_table_version(thd, alter_ctx.db,
18419 backup_name))
18420 goto err_with_mdl;
18421
18422
2/4
✓ Branch 0 taken 6215 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6215 times.
6215 if (thd->dd_client()->store(non_dd_table_def.get())) goto err_with_mdl;
18423
18424 6215 const dd::Table *stored_table = nullptr;
18425
18426
4/8
✓ Branch 0 taken 6215 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6215 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6215 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 6215 times.
6215 if (thd->dd_client()->acquire(alter_ctx.new_db, alter_ctx.tmp_name,
18427 &stored_table)) {
18428 DBUG_LOG("zip_dict",
18429 "Acquiring dictionary table object failed "
18430 " for query "
18431 << thd->query().str << " table_db: " << alter_ctx.new_db
18432 << " table_name: " << alter_ctx.tmp_name);
18433
18434 goto err_with_mdl;
18435 }
18436
18437
2/4
✓ Branch 0 taken 6215 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6215 times.
6215 if (compression_dict::cols_table_insert(thd, *stored_table))
18438 goto err_with_mdl;
18439
18440 // Safety, in-memory dd::Table is no longer totally correct.
18441 6215 non_dd_table_def.reset();
18442 }
18443
18444 // Rename the new table to the correct name.
18445 55031 if (mysql_rename_table(
18446 thd, new_db_type, alter_ctx.new_db, alter_ctx.tmp_name, alter_ctx.db,
18447 alter_ctx.table_name, *new_schema, alter_ctx.new_db,
18448 alter_ctx.new_alias,
18449 (FN_FROM_IS_TMP |
18450 18353 ((new_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) ? NO_DD_COMMIT
18451
1/2
✓ Branch 0 taken 18339 times.
✗ Branch 1 not taken.
18353 : 0) |
18452
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 18241 times.
18353 (alter_ctx.is_table_renamed() ? 0 : NO_FK_RENAME | NO_CC_RENAME))) ||
18453
2/2
✓ Branch 0 taken 6880 times.
✓ Branch 1 taken 11454 times.
18334 ((new_db_type->flags & HTON_SUPPORTS_FOREIGN_KEYS) &&
18454
2/4
✓ Branch 0 taken 6880 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6880 times.
✗ Branch 3 not taken.
6880 adjust_fks_for_complex_alter_table(thd, table_list, &alter_ctx,
18455 alter_info, new_db_type,
18456
4/4
✓ Branch 0 taken 18334 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 18334 times.
36673 &fk_invalidator)) ||
18457 /*
18458 Try commit changes if ALTER TABLE as whole is not atomic and we have
18459 not done this in the above mysql_rename_table() call.
18460 */
18461
4/4
✓ Branch 0 taken 12136 times.
✓ Branch 1 taken 6198 times.
✓ Branch 2 taken 682 times.
✓ Branch 3 taken 11454 times.
18334 (!atomic_replace && (new_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) &&
18462
2/4
✓ Branch 0 taken 682 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 682 times.
682 trans_intermediate_ddl_commit(thd, false))) {
18463 // Rename failed, delete the temporary table.
18464
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (!atomic_replace) {
18465
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (new_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) {
18466 /*
18467 If ALTER TABLE as whole is not atomic and the above rename or
18468 FK changes have failed without cleaning up after themselves,
18469 we need to do this now.
18470 */
18471
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 (void)trans_intermediate_ddl_commit(thd, true);
18472 }
18473
18474 /*
18475 In non-atomic mode situations when the SE has requested rollback
18476 should be handled already.
18477 */
18478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(!thd->transaction_rollback_request);
18479
18480
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 (void)quick_rm_table(thd, new_db_type, alter_ctx.new_db,
18481 alter_ctx.tmp_name, FN_IS_TMP);
18482
18483 // Restore the backup of the original table to its original name.
18484 // If the operation fails, we need to retry it to avoid leaving
18485 // the dictionary inconsistent.
18486 //
18487 // This hack might become unnecessary once InnoDB stops acquiring
18488 // gap locks on DD tables (which might cause deadlocks).
18489 2 uint retries = 20;
18490
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
4 while (retries-- &&
18491
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 mysql_rename_table(
18492 thd, old_db_type, alter_ctx.db, backup_name, alter_ctx.db,
18493 backup_name, *schema, alter_ctx.db, alter_ctx.alias,
18494 FN_FROM_IS_TMP | NO_FK_CHECKS | NO_FK_RENAME | NO_CC_RENAME))
18495 ;
18496 }
18497 5 goto err_with_mdl;
18498 }
18499
18500 /*
18501 If ALTER TABLE is non-atomic and fails after this point it can add
18502 foreign keys and such addition won't be reverted. So we need to
18503 invalidate table objects for foreign key parents even on error.
18504 */
18505
2/2
✓ Branch 0 taken 12136 times.
✓ Branch 1 taken 6198 times.
18334 if (!atomic_replace) invalidate_fk_parents_on_error = true;
18506
18507 // Handle trigger name, check constraint names and histograms statistics.
18508 {
18509 18334 dd::Table *backup_table = nullptr;
18510 18334 dd::Table *new_dd_table = nullptr;
18511
3/10
✓ Branch 0 taken 18334 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18334 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 18334 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
36668 if (thd->dd_client()->acquire_for_modification(alter_ctx.db, backup_name,
18512
3/6
✓ Branch 0 taken 18334 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18334 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18334 times.
✗ Branch 5 not taken.
55002 &backup_table) ||
18513
7/18
✓ Branch 0 taken 18334 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18334 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18334 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 18334 times.
✓ Branch 8 taken 18334 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 18334 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 18334 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
36668 thd->dd_client()->acquire_for_modification(
18514 alter_ctx.new_db, alter_ctx.new_alias, &new_dd_table))
18515 goto err_with_mdl;
18516
2/4
✓ Branch 0 taken 18334 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18334 times.
✗ Branch 3 not taken.
18334 assert(backup_table != nullptr && new_dd_table != nullptr);
18517
18518 /*
18519 Check if this is an ALTER command that will cause histogram statistics to
18520 become invalid. If that is the case; remove the histogram statistics.
18521
18522 This will take care of scenarios when COPY alter is used, but not INPLACE.
18523 Do this before the commit for non-transactional tables, because the
18524 new_dd_table is invalidated on commit.
18525 */
18526
2/4
✓ Branch 0 taken 18334 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18334 times.
18334 if (alter_table_drop_histograms(thd, table_list, alter_info, create_info,
18527 columns, backup_table, new_dd_table))
18528 goto err_with_mdl; /* purecov: deadcode */
18529
18530
1/2
✓ Branch 0 taken 18334 times.
✗ Branch 1 not taken.
18334 bool update = (new_dd_table->check_constraints()->size() > 0);
18531 // Set mode for new_dd_table's check constraints.
18532
1/2
✓ Branch 0 taken 18334 times.
✗ Branch 1 not taken.
18334 set_check_constraints_alter_mode(new_dd_table, alter_info);
18533
18534 /*
18535 Check constraint names are unique per schema, we cannot create them while
18536 both table version exists. Adjust check constraint names in old table
18537 version.
18538 */
18539
2/4
✓ Branch 0 taken 18334 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18334 times.
18334 if (adjust_check_constraint_names_for_old_table_version(thd, alter_ctx.db,
18540 backup_table))
18541 goto err_with_mdl;
18542
18543 // Reset check constraint's mode.
18544
1/2
✓ Branch 0 taken 18334 times.
✗ Branch 1 not taken.
18334 reset_check_constraints_alter_mode(new_dd_table);
18545
18546 /*
18547 Since trigger names have to be unique per schema, we cannot
18548 create them while both the old and the tmp version of the
18549 table exist.
18550 */
18551
3/4
✓ Branch 0 taken 18334 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 18306 times.
18334 if (backup_table->has_trigger()) {
18552
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 new_dd_table->copy_triggers(backup_table);
18553
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 backup_table->drop_all_triggers();
18554 28 update = true;
18555 }
18556
5/6
✓ Branch 0 taken 18334 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18236 times.
✓ Branch 3 taken 98 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 18321 times.
36570 if (!is_checked_for_upgrade(*new_dd_table) &&
18557
3/4
✓ Branch 0 taken 18236 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 18223 times.
18236 is_checked_for_upgrade(*backup_table)) {
18558
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 new_dd_table->mark_as_checked_for_upgrade();
18559 13 update = true;
18560 }
18561
2/2
✓ Branch 0 taken 493 times.
✓ Branch 1 taken 17841 times.
18334 if (update) {
18562
3/6
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 493 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 493 times.
986 if (thd->dd_client()->update(backup_table) ||
18563
2/4
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 493 times.
493 thd->dd_client()->update(new_dd_table))
18564 goto err_with_mdl;
18565
18566 /* Prevent intermediate commits to invoke commit order */
18567
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 Implicit_substatement_state_guard substatement_guard(thd);
18568
7/12
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 456 times.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 37 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 37 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 493 times.
493 if (!atomic_replace && (trans_commit_stmt(thd) || trans_commit(thd)))
18569 goto err_with_mdl;
18570
1/2
✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
493 }
18571 }
18572
18573 // If the ALTER command was a rename, rename any existing histograms.
18574
3/4
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 18222 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18334 times.
18446 if (alter_ctx.is_table_renamed() &&
18575
2/4
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 112 times.
112 rename_histograms(thd, table_list->db, table_list->table_name, new_db,
18576 new_name)) {
18577 goto err_with_mdl; /* purecov: deadcode */
18578 }
18579
18580 // ALTER TABLE succeeded, delete the backup of the old table.
18581
4/6
✓ Branch 0 taken 6198 times.
✓ Branch 1 taken 12136 times.
✓ Branch 2 taken 18320 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 18320 times.
18334 if (quick_rm_table(thd, old_db_type, alter_ctx.db, backup_name,
18582 FN_IS_TMP | (atomic_replace ? NO_DD_COMMIT : 0))) {
18583 /*
18584 The fact that deletion of the backup failed is not critical
18585 error, but still worth reporting as it might indicate serious
18586 problem with server.
18587
18588 TODO: In !atomic_replace case we might need to do FK parents
18589 invalidation here. However currently our FKs are not
18590 even named correctly at this point, so we postpone
18591 fixing this issue until we solve FK naming problem.
18592 */
18593 goto err_with_mdl;
18594 }
18595
18596 18320 end_inplace_noop:
18597
18598
1/2
✓ Branch 0 taken 18554 times.
✗ Branch 1 not taken.
18554 THD_STAGE_INFO(thd, stage_end);
18599
18600
2/6
✓ Branch 0 taken 18554 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18554 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
18554 DBUG_EXECUTE_IF("sleep_alter_before_main_binlog", my_sleep(6000000););
18601
3/4
✓ Branch 0 taken 18357 times.
✓ Branch 1 taken 197 times.
✓ Branch 2 taken 18357 times.
✗ Branch 3 not taken.
18554 DEBUG_SYNC(thd, "alter_table_before_main_binlog");
18602
18603 37108 ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
18604
3/6
✓ Branch 0 taken 18554 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18554 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18554 times.
✗ Branch 5 not taken.
18554 thd->query().str, thd->query().length, alter_ctx.db,
18605 alter_ctx.table_name);
18606
18607
5/6
✓ Branch 0 taken 14591 times.
✓ Branch 1 taken 3963 times.
✓ Branch 2 taken 14173 times.
✓ Branch 3 taken 418 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 14173 times.
18554 assert(!(mysql_bin_log.is_open() &&
18608 thd->is_current_stmt_binlog_format_row() &&
18609 (create_info->options & HA_LEX_CREATE_TMP_TABLE)));
18610
18611 /*
18612 If this is no-op ALTER TABLE we don't have transaction started.
18613 We can't use binlog's trx cache in this case as it requires active
18614 transaction with valid XID.
18615 */
18616
5/8
✓ Branch 0 taken 18554 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18554 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18554 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 18550 times.
18554 if (write_bin_log(thd, true, thd->query().str, thd->query().length,
18617
4/4
✓ Branch 0 taken 6332 times.
✓ Branch 1 taken 12222 times.
✓ Branch 2 taken 6184 times.
✓ Branch 3 taken 148 times.
18554 atomic_replace && !is_noop))
18618 4 goto err_with_mdl;
18619
18620
2/2
✓ Branch 0 taken 18316 times.
✓ Branch 1 taken 234 times.
18550 if (!is_noop) {
18621
1/2
✓ Branch 0 taken 18316 times.
✗ Branch 1 not taken.
18316 Uncommitted_tables_guard uncommitted_tables(thd);
18622
18623
1/2
✓ Branch 0 taken 18316 times.
✗ Branch 1 not taken.
18316 uncommitted_tables.add_table(table_list);
18624
18625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18316 times.
18316 if (update_referencing_views_metadata(thd, table_list, new_db, new_name,
18626
1/2
✓ Branch 0 taken 18316 times.
✗ Branch 1 not taken.
18316 !atomic_replace, &uncommitted_tables))
18627 goto err_with_mdl;
18628
18629
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 18208 times.
18316 if (alter_ctx.is_table_renamed())
18630
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 tdc_remove_table(thd, TDC_RT_REMOVE_ALL, alter_ctx.new_db,
18631 alter_ctx.new_name, false);
18632
1/2
✓ Branch 0 taken 18316 times.
✗ Branch 1 not taken.
18316 }
18633
18634 // Commit if it was not done before in order to be able to reopen tables.
18635
7/12
✓ Branch 0 taken 6331 times.
✓ Branch 1 taken 12219 times.
✓ Branch 2 taken 6331 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6331 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6328 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 6328 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 18547 times.
18550 if (atomic_replace && (trans_commit_stmt(thd) || trans_commit_implicit(thd)))
18636 goto err_with_mdl;
18637
18638
3/4
✓ Branch 0 taken 7009 times.
✓ Branch 1 taken 11538 times.
✓ Branch 2 taken 7009 times.
✗ Branch 3 not taken.
18547 if ((new_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) && new_db_type->post_ddl)
18639
1/2
✓ Branch 0 taken 7001 times.
✗ Branch 1 not taken.
7009 new_db_type->post_ddl(thd);
18640
3/4
✓ Branch 0 taken 6393 times.
✓ Branch 1 taken 12146 times.
✓ Branch 2 taken 6393 times.
✗ Branch 3 not taken.
18539 if ((old_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) && old_db_type->post_ddl)
18641
1/2
✓ Branch 0 taken 6393 times.
✗ Branch 1 not taken.
6393 old_db_type->post_ddl(thd);
18642
18643 #ifndef WORKAROUND_TO_BE_REMOVED_BY_WL6049
18644 {
18645 TABLE_LIST table_list_reopen(alter_ctx.new_db, alter_ctx.new_name,
18646
1/2
✓ Branch 0 taken 18539 times.
✗ Branch 1 not taken.
18539 alter_ctx.new_alias, TL_READ);
18647 18539 table_list_reopen.mdl_request.ticket =
18648
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 18431 times.
18539 alter_ctx.is_table_renamed() ? alter_ctx.target_mdl_request.ticket
18649 : mdl_ticket;
18650
18651
1/2
✓ Branch 0 taken 18539 times.
✗ Branch 1 not taken.
18539 Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN);
18652
18653
2/4
✓ Branch 0 taken 18539 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18539 times.
18539 if (open_table(thd, &table_list_reopen, &ot_ctx)) return true;
18654
18655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18539 times.
18539 assert(table_list_reopen.table == thd->open_tables);
18656
1/2
✓ Branch 0 taken 18539 times.
✗ Branch 1 not taken.
18539 close_thread_table(thd, &thd->open_tables);
18657 }
18658 #endif
18659
18660 75251 end_inplace:
18661
18662
1/2
✓ Branch 0 taken 75251 times.
✗ Branch 1 not taken.
75251 fk_invalidator.invalidate(thd);
18663
18664
2/2
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 74985 times.
75251 if (alter_ctx.is_table_renamed())
18665
1/2
✓ Branch 0 taken 266 times.
✗ Branch 1 not taken.
266 thd->locked_tables_list.rename_locked_table(
18666 table_list, alter_ctx.new_db, alter_ctx.new_name,
18667 alter_ctx.target_mdl_request.ticket);
18668
18669 {
18670
1/2
✓ Branch 0 taken 75251 times.
✗ Branch 1 not taken.
75251 bool reopen_error = thd->locked_tables_list.reopen_tables(thd);
18671
18672
2/2
✓ Branch 0 taken 75168 times.
✓ Branch 1 taken 83 times.
75251 if (thd->locked_tables_mode == LTM_LOCK_TABLES ||
18673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75168 times.
75168 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) {
18674
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 71 times.
83 if (alter_ctx.is_table_renamed()) {
18675 /*
18676 Release metadata lock on old table name and keep the lock
18677 on the new one. We have to ignore reopen_error in this case
18678 as we will mess up FK invariants for LOCK TABLES otherwise.
18679 */
18680
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 thd->mdl_context.release_all_locks_for_name(mdl_ticket);
18681
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 thd->mdl_context.set_lock_duration(alter_ctx.target_mdl_request.ticket,
18682 MDL_EXPLICIT);
18683
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 alter_ctx.target_mdl_request.ticket->downgrade_lock(
18684 MDL_SHARED_NO_READ_WRITE);
18685
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if (alter_ctx.is_database_changed())
18686
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 thd->mdl_context.set_lock_duration(
18687 alter_ctx.target_db_mdl_request.ticket, MDL_EXPLICIT);
18688 } else
18689
1/2
✓ Branch 0 taken 71 times.
✗ Branch 1 not taken.
71 mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
18690 }
18691
18692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75251 times.
75251 if (reopen_error) return true;
18693 }
18694
18695 75251 end_temporary:
18696 152784 snprintf(alter_ctx.tmp_name, sizeof(alter_ctx.tmp_name),
18697
1/2
✓ Branch 0 taken 76392 times.
✗ Branch 1 not taken.
76392 ER_THD(thd, ER_INSERT_INFO), (long)(copied + deleted), (long)deleted,
18698 76392 (long)thd->get_stmt_da()->current_statement_cond_count());
18699
1/2
✓ Branch 0 taken 76392 times.
✗ Branch 1 not taken.
76392 my_ok(thd, copied + deleted, 0L, alter_ctx.tmp_name);
18700 76392 return false;
18701
18702 1504 err_new_table_cleanup:
18703
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1495 times.
1504 if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
18704
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 if (new_table)
18705
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 close_temporary_table(thd, new_table, true, true);
18706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 else if (!no_ha_table)
18707 rm_temporary_table(thd, new_db_type, alter_ctx.get_tmp_path(),
18708 non_dd_table_def.get());
18709 } else {
18710 /* close_temporary_table() frees the new_table pointer. */
18711
3/4
✓ Branch 0 taken 974 times.
✓ Branch 1 taken 521 times.
✓ Branch 2 taken 974 times.
✗ Branch 3 not taken.
1495 if (new_table) close_temporary_table(thd, new_table, true, false);
18712
18713
2/2
✓ Branch 0 taken 995 times.
✓ Branch 1 taken 500 times.
1495 if (!(new_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL)) {
18714
2/2
✓ Branch 0 taken 115 times.
✓ Branch 1 taken 880 times.
995 if (no_ha_table) // Only remove from DD.
18715 {
18716 dd::cache::Dictionary_client::Auto_releaser releaser_3(
18717
1/2
✓ Branch 0 taken 115 times.
✗ Branch 1 not taken.
115 thd->dd_client());
18718 115 const dd::Table *drop_table_def = nullptr;
18719
4/8
✓ Branch 0 taken 115 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 115 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 115 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 115 times.
✗ Branch 7 not taken.
115 if (!thd->dd_client()->acquire(alter_ctx.new_db, alter_ctx.tmp_name,
18720 &drop_table_def)) {
18721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 115 times.
115 assert(drop_table_def != nullptr);
18722
1/2
✓ Branch 0 taken 115 times.
✗ Branch 1 not taken.
115 bool result = dd::drop_table(thd, alter_ctx.new_db,
18723 alter_ctx.tmp_name, *drop_table_def);
18724
1/2
✓ Branch 0 taken 115 times.
✗ Branch 1 not taken.
115 (void)trans_intermediate_ddl_commit(thd, result);
18725 }
18726 115 } else // Remove from both DD and SE.
18727
1/2
✓ Branch 0 taken 880 times.
✗ Branch 1 not taken.
880 (void)quick_rm_table(thd, new_db_type, alter_ctx.new_db,
18728 alter_ctx.tmp_name, FN_IS_TMP);
18729 } else {
18730
1/2
✓ Branch 0 taken 500 times.
✗ Branch 1 not taken.
500 trans_rollback_stmt(thd);
18731 /*
18732 Full rollback in case we have THD::transaction_rollback_request
18733 and to synchronize DD state in cache and on disk (as statement
18734 rollback doesn't clear DD cache of modified uncommitted objects).
18735 */
18736
1/2
✓ Branch 0 taken 500 times.
✗ Branch 1 not taken.
500 trans_rollback(thd);
18737 }
18738
2/2
✓ Branch 0 taken 500 times.
✓ Branch 1 taken 995 times.
1495 if ((new_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) &&
18739
1/2
✓ Branch 0 taken 500 times.
✗ Branch 1 not taken.
500 new_db_type->post_ddl)
18740
1/2
✓ Branch 0 taken 500 times.
✗ Branch 1 not taken.
500 new_db_type->post_ddl(thd);
18741 }
18742
18743
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1491 times.
1504 if (alter_ctx.error_if_not_empty &
18744 Alter_table_ctx::GEOMETRY_WITHOUT_DEFAULT) {
18745
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 my_error(ER_INVALID_USE_OF_NULL, MYF(0));
18746 }
18747
18748 /*
18749 No default value was provided for a DATE/DATETIME field, the
18750 current sql_mode doesn't allow the '0000-00-00' value and
18751 the table to be altered isn't empty.
18752 Report error here. Ignore error checkin for push_zero_date_warning()
18753 as we return true right below.
18754 */
18755 3008 if ((alter_ctx.error_if_not_empty &
18756 8 Alter_table_ctx::DATETIME_WITHOUT_DEFAULT) &&
18757
6/8
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1496 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 1496 times.
1512 (thd->variables.sql_mode & MODE_NO_ZERO_DATE) &&
18758 8 thd->get_stmt_da()->current_row_for_condition()) {
18759
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 (void)push_zero_date_warning(thd, alter_ctx.datetime_field);
18760 }
18761 1504 return true;
18762
18763 14 err_with_mdl:
18764 /*
18765 An error happened while we were holding exclusive name metadata lock
18766 on table being altered. Before releasing locks we need to rollback
18767 changes to the data-dictionary, storage angine and binary log (if
18768 they were not committed earlier) and execute post DDL hooks.
18769 We also try to reopen old version of the table under LOCK TABLES
18770 if possible.
18771 */
18772
18773
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 trans_rollback_stmt(thd);
18774 /*
18775 Full rollback in case we have THD::transaction_rollback_request
18776 and to synchronize DD state in cache and on disk (as statement
18777 rollback doesn't clear DD cache of modified uncommitted objects).
18778 */
18779
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 trans_rollback(thd);
18780
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
14 if ((new_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) && new_db_type->post_ddl)
18781
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 new_db_type->post_ddl(thd);
18782
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
14 if ((old_db_type->flags & HTON_SUPPORTS_ATOMIC_DDL) && old_db_type->post_ddl)
18783
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 old_db_type->post_ddl(thd);
18784
18785
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
14 if (atomic_replace) {
18786 /*
18787 If both old and new storage engines support atomic DDL all changes
18788 were reverted at this point. So we can safely try to reopen table
18789 under old name.
18790 */
18791 } else {
18792 /*
18793 If ALTER TABLE ... RENAME ... ALGORITHM=COPY is non-atomic we can't
18794 be sure that rename step was reverted, so we simply remove table
18795 from the list of locked tables.
18796 */
18797
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
10 if (alter_ctx.is_table_renamed())
18798
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 thd->locked_tables_list.unlink_all_closed_tables(thd, nullptr, 0);
18799 }
18800
18801 /*
18802 ALTER TABLE which changes table storage engine from MyISAM to InnoDB
18803 and adds foreign keys at the same time can fail after installing
18804 new table version. In this case we still need to invalidate table
18805 objects for parent tables to avoid creating discrepancy between
18806 data-dictionary and cache contents.
18807 */
18808
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
14 if (invalidate_fk_parents_on_error) fk_invalidator.invalidate(thd);
18809
18810
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 (void)thd->locked_tables_list.reopen_tables(thd);
18811
18812
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
14 if ((thd->locked_tables_mode == LTM_LOCK_TABLES ||
18813
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) {
18814 /*
18815 Non-atomic ALTER TABLE ... RENAME ... ALGORITHM=COPY can add
18816 foreign keys if at the same time SE is changed from, e.g.,
18817 MyISAM to InnoDB. Since releasing metadata locks on old or new
18818 table name can break FK invariants for LOCK TABLES in various
18819 scenarios we keep both of them.
18820 */
18821
5/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 1 times.
4 if (!atomic_replace && alter_ctx.is_table_renamed()) {
18822
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 thd->mdl_context.set_lock_duration(alter_ctx.target_mdl_request.ticket,
18823 MDL_EXPLICIT);
18824
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 alter_ctx.target_mdl_request.ticket->downgrade_lock(
18825 MDL_SHARED_NO_READ_WRITE);
18826
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (alter_ctx.is_database_changed())
18827
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 thd->mdl_context.set_lock_duration(
18828 alter_ctx.target_db_mdl_request.ticket, MDL_EXPLICIT);
18829 }
18830
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
18831 }
18832
18833 14 return true;
18834 91451 }
18835 /* mysql_alter_table */
18836
18837 /**
18838 Prepare the transaction for the alter table's copy phase.
18839 */
18840
18841 13461 bool mysql_trans_prepare_alter_copy_data(THD *thd) {
18842
1/2
✓ Branch 0 taken 13461 times.
✗ Branch 1 not taken.
13461 DBUG_TRACE;
18843 /*
18844 Turn off recovery logging since rollback of an alter table is to
18845 delete the new table so there is no need to log the changes to it.
18846
18847 This needs to be done before external_lock.
18848
18849 Also this prevent intermediate commits to invoke commit order.
18850 */
18851
1/2
✓ Branch 0 taken 13461 times.
✗ Branch 1 not taken.
13461 Implicit_substatement_state_guard substatement_guard(thd);
18852
18853
2/4
✓ Branch 0 taken 13461 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13461 times.
13461 if (ha_enable_transaction(thd, false)) return true;
18854 13461 return false;
18855 13461 }
18856
18857 /**
18858 Commit the copy phase of the alter table.
18859 */
18860
18861 13455 bool mysql_trans_commit_alter_copy_data(THD *thd) {
18862 13455 bool error = false;
18863
1/2
✓ Branch 0 taken 13455 times.
✗ Branch 1 not taken.
13455 DBUG_TRACE;
18864
18865 /*
18866 Ensure that ha_commit_trans() which is implicitly called by
18867 ha_enable_transaction() doesn't update GTID and slave info states.
18868 Also this prevent intermediate commits to invoke commit order.
18869 */
18870
1/2
✓ Branch 0 taken 13455 times.
✗ Branch 1 not taken.
13455 Implicit_substatement_state_guard substatement_guard(thd);
18871
2/4
✓ Branch 0 taken 13455 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13455 times.
13455 if (ha_enable_transaction(thd, true)) return true;
18872
18873 /*
18874 Ensure that the new table is saved properly to disk before installing
18875 the new .frm.
18876 And that InnoDB's internal latches are released, to avoid deadlock
18877 when waiting on other instances of the table before rename (Bug#54747).
18878 */
18879
2/4
✓ Branch 0 taken 13455 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13455 times.
13455 if (trans_commit_stmt(thd)) error = true;
18880
2/4
✓ Branch 0 taken 13455 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13455 times.
13455 if (trans_commit_implicit(thd)) error = true;
18881
18882 13455 return error;
18883 13455 }
18884
18885 20471 static int copy_data_between_tables(
18886 THD *thd, PSI_stage_progress *psi [[maybe_unused]], TABLE *from, TABLE *to,
18887 List<Create_field> &create, ha_rows *copied, ha_rows *deleted,
18888 Alter_info::enum_enable_or_disable keys_onoff, Alter_table_ctx *alter_ctx,
18889 bool expand_fast_index_creation) {
18890
1/2
✓ Branch 0 taken 20471 times.
✗ Branch 1 not taken.
20471 DBUG_TRACE;
18891
18892 int error;
18893 Copy_field *copy, *copy_end;
18894 Field **ptr;
18895 /*
18896 Fields which values need to be generated for each row, i.e. either
18897 generated fields or newly added fields with generated default values.
18898 */
18899 Field **gen_fields, **gen_fields_end;
18900 20471 bool auto_increment_field_copied = false;
18901 sql_mode_t save_sql_mode;
18902 20471 Query_expression *const unit = thd->lex->unit;
18903 20471 Query_block *const select = unit->first_query_block();
18904
18905 /*
18906 If target storage engine supports atomic DDL we should not commit
18907 and disable transaction to let SE do proper cleanup on error/crash.
18908 Such engines should be smart enough to disable undo/redo logging
18909 for target table automatically.
18910 Temporary tables path doesn't employ atomic DDL support so disabling
18911 transaction is OK. Moreover doing so allows to not interfere with
18912 concurrent FLUSH TABLES WITH READ LOCK.
18913 */
18914 49002 if ((!(to->file->ht->flags & HTON_SUPPORTS_ATOMIC_DDL) ||
18915
5/6
✓ Branch 0 taken 8060 times.
✓ Branch 1 taken 12411 times.
✓ Branch 2 taken 1050 times.
✓ Branch 3 taken 7010 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 20471 times.
33932 from->s->tmp_table) &&
18916
2/4
✓ Branch 0 taken 13461 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13461 times.
13461 mysql_trans_prepare_alter_copy_data(thd))
18917 return -1;
18918
18919
6/10
✓ Branch 0 taken 20471 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20471 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 108508 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 108508 times.
✓ Branch 7 taken 20471 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 20471 times.
128979 if (!(copy = new (thd->mem_root) Copy_field[to->s->fields]))
18920 return -1; /* purecov: inspected */
18921
18922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20471 times.
20471 if (!(gen_fields = thd->mem_root->ArrayAlloc<Field *>(
18923
1/2
✓ Branch 0 taken 20471 times.
✗ Branch 1 not taken.
20471 to->s->gen_def_field_count + to->s->vfields))) {
18924 destroy_array(copy, to->s->fields);
18925 return -1;
18926 }
18927
18928
2/4
✓ Branch 0 taken 20471 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 20471 times.
20471 if (to->file->ha_external_lock(thd, F_WRLCK)) {
18929 destroy_array(copy, to->s->fields);
18930 return -1;
18931 }
18932
18933 /* We need external lock before we can disable/enable keys */
18934
2/4
✓ Branch 0 taken 20471 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20471 times.
✗ Branch 3 not taken.
20471 alter_table_manage_keys(thd, to, from->file->indexes_are_disabled(),
18935 keys_onoff);
18936
18937
2/2
✓ Branch 0 taken 5277 times.
✓ Branch 1 taken 15194 times.
20471 if (unit->is_prepared()) {
18938
1/2
✓ Branch 0 taken 5277 times.
✗ Branch 1 not taken.
5277 bind_fields(thd->stmt_arena->item_list());
18939 }
18940 /*
18941 We want warnings/errors about data truncation emitted when we
18942 copy data to new version of table.
18943 */
18944 20471 thd->check_for_truncated_fields = CHECK_FIELD_WARN;
18945 20471 thd->num_truncated_fields = 0L;
18946
18947
1/2
✓ Branch 0 taken 20471 times.
✗ Branch 1 not taken.
20471 from->file->info(HA_STATUS_VARIABLE);
18948
1/2
✓ Branch 0 taken 20471 times.
✗ Branch 1 not taken.
20471 to->file->ha_start_bulk_insert(from->file->stats.records);
18949
18950 20471 mysql_stage_set_work_estimated(psi, from->file->stats.records);
18951
18952 20471 save_sql_mode = thd->variables.sql_mode;
18953
18954
1/2
✓ Branch 0 taken 20471 times.
✗ Branch 1 not taken.
20471 List_iterator<Create_field> it(create);
18955 const Create_field *def;
18956 20471 copy_end = copy;
18957 20471 gen_fields_end = gen_fields;
18958
2/2
✓ Branch 0 taken 108508 times.
✓ Branch 1 taken 20471 times.
128979 for (ptr = to->field; *ptr; ptr++) {
18959 108508 def = it++;
18960
2/2
✓ Branch 0 taken 4524 times.
✓ Branch 1 taken 103984 times.
108508 if ((*ptr)->is_gcol()) {
18961 /*
18962 Values in generated columns need to be (re)generated even for
18963 pre-existing columns, as they might depend on other columns,
18964 values in which might have changed as result of this ALTER.
18965 Because of this there is no sense in copying old values for
18966 these columns.
18967 TODO: Figure out if we can avoid even reading these old values
18968 from SE.
18969 */
18970 4524 *(gen_fields_end++) = *ptr;
18971 4524 continue;
18972 }
18973 // Array fields will be properly generated during GC update loop below
18974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103984 times.
103984 assert(!def->is_array);
18975
2/2
✓ Branch 0 taken 100285 times.
✓ Branch 1 taken 3699 times.
103984 if (def->field) {
18976
2/2
✓ Branch 0 taken 643 times.
✓ Branch 1 taken 99642 times.
100285 if (*ptr == to->next_number_field) {
18977 643 auto_increment_field_copied = true;
18978 /*
18979 If we are going to copy contents of one auto_increment column to
18980 another auto_increment column it is sensible to preserve zeroes.
18981 This condition also covers case when we are don't actually alter
18982 auto_increment column.
18983 */
18984
2/2
✓ Branch 0 taken 596 times.
✓ Branch 1 taken 47 times.
643 if (def->field == from->found_next_number_field)
18985 596 thd->variables.sql_mode |= MODE_NO_AUTO_VALUE_ON_ZERO;
18986 }
18987
1/2
✓ Branch 0 taken 100285 times.
✗ Branch 1 not taken.
100285 (copy_end++)->set(*ptr, def->field);
18988 } else {
18989 /*
18990 New column. Add it to the array of columns requiring value
18991 generation if it has generated default.
18992 */
18993
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 3602 times.
3699 if ((*ptr)->has_insert_default_general_value_expression()) {
18994
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
97 assert(!((*ptr)->is_gcol()));
18995 97 *(gen_fields_end++) = *ptr;
18996 }
18997 }
18998 }
18999
19000 20471 ulong found_count = 0;
19001 20471 ulong delete_count = 0;
19002
19003 20471 ORDER *order = select->order_list.first;
19004
19005 20471 unique_ptr_destroy_only<Filesort> fsort;
19006 20471 unique_ptr_destroy_only<RowIterator> iterator;
19007 AccessPath *path =
19008
1/2
✓ Branch 0 taken 20471 times.
✗ Branch 1 not taken.
20471 create_table_access_path(thd, from, nullptr, nullptr, nullptr,
19009 /*count_examined_rows=*/false);
19010
19011
6/6
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 20412 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 43 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 20461 times.
20487 if (order != nullptr && to->s->primary_key != MAX_KEY &&
19012
3/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 6 times.
16 to->file->primary_key_is_clustered()) {
19013 char warn_buff[MYSQL_ERRMSG_SIZE];
19014 10 snprintf(warn_buff, sizeof(warn_buff),
19015 "ORDER BY ignored as there is a user-defined clustered index"
19016 " in the table '%-.192s'",
19017 10 from->s->table_name.str);
19018
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 push_warning(thd, Sql_condition::SL_WARNING, ER_UNKNOWN_ERROR, warn_buff);
19019 10 order = nullptr;
19020 }
19021 /* Tell handler that we have values for all columns in the to table */
19022
1/2
✓ Branch 0 taken 20471 times.
✗ Branch 1 not taken.
20471 to->use_all_columns();
19023
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 20422 times.
20471 if (order != nullptr) {
19024
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 TABLE_LIST tables;
19025 49 tables.table = from;
19026 49 tables.alias = tables.table_name = from->s->table_name.str;
19027 49 tables.db = from->s->db.str;
19028 49 error = 1;
19029
19030
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 if (!unit->is_prepared()) {
19031 49 Column_privilege_tracker column_privilege(thd, SELECT_ACL);
19032
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
49 if (select->setup_base_ref_items(thd)) {
19033 goto err; /* purecov: inspected */
19034 }
19035 49 mem_root_deque<Item *> fields(thd->mem_root);
19036
3/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 48 times.
49 if (setup_order(thd, select->base_ref_items, &tables, &fields, order))
19037 1 goto err;
19038
4/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 1 times.
50 }
19039
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
96 fsort.reset(new (thd->mem_root) Filesort(
19040 thd, {from}, /*keep_buffers=*/false, order, HA_POS_ERROR,
19041 /*remove_duplicates=*/false, /*force_sort_rowids=*/true,
19042
2/4
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
48 /*unwrap_rollup=*/false));
19043
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 path = NewSortAccessPath(thd, path, fsort.get(),
19044 /*count_examined_rows=*/false);
19045 }
19046
19047
3/4
✓ Branch 0 taken 15193 times.
✓ Branch 1 taken 5277 times.
✓ Branch 2 taken 15193 times.
✗ Branch 3 not taken.
20470 if (!unit->is_prepared()) unit->set_prepared();
19048
19049
1/2
✓ Branch 0 taken 20470 times.
✗ Branch 1 not taken.
40940 iterator = CreateIteratorFromAccessPath(thd, path, /*join=*/nullptr,
19050 20470 /*eligible_for_batch_mode=*/true);
19051 // Prevent cleanup in QEP_shared_owner::qs_cleanup(),
19052 // to avoid double-destroy of the SortingIterator.
19053 20470 from->sorting_iterator = nullptr;
19054
4/8
✓ Branch 0 taken 20470 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20470 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 20470 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 20470 times.
20470 if (iterator == nullptr || iterator->Init()) {
19055 error = 1;
19056 goto err;
19057 }
19058 20470 thd->get_stmt_da()->reset_current_row_for_condition();
19059
19060
1/2
✓ Branch 0 taken 20470 times.
✗ Branch 1 not taken.
20470 set_column_static_defaults(to, create);
19061
19062
3/4
✓ Branch 0 taken 3228190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3208670 times.
✓ Branch 3 taken 19520 times.
3228190 while (!(error = iterator->Read())) {
19063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3208670 times.
3208670 if (thd->killed) {
19064 thd->send_kill_message();
19065 error = 1;
19066 break;
19067 }
19068 /*
19069 Return error if source table isn't empty.
19070
19071 For a DATE/DATETIME field, return error only if strict mode
19072 and No ZERO DATE mode is enabled.
19073 */
19074 6417340 if ((alter_ctx->error_if_not_empty &
19075
4/4
✓ Branch 0 taken 3208665 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 3208657 times.
6417335 Alter_table_ctx::GEOMETRY_WITHOUT_DEFAULT) ||
19076
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 3208654 times.
3208665 ((alter_ctx->error_if_not_empty &
19077 11 Alter_table_ctx::DATETIME_WITHOUT_DEFAULT) &&
19078
4/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1 times.
20 (thd->variables.sql_mode & MODE_NO_ZERO_DATE) &&
19079 9 thd->is_strict_mode())) {
19080 13 error = 1;
19081 13 break;
19082 }
19083
2/2
✓ Branch 0 taken 195491 times.
✓ Branch 1 taken 3013166 times.
3208657 if (to->next_number_field) {
19084
2/2
✓ Branch 0 taken 195367 times.
✓ Branch 1 taken 124 times.
195491 if (auto_increment_field_copied)
19085 195367 to->autoinc_field_has_explicit_non_null_value = true;
19086 else
19087
1/2
✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
124 to->next_number_field->reset();
19088 }
19089
19090
2/2
✓ Branch 0 taken 9342019 times.
✓ Branch 1 taken 3208657 times.
12550676 for (Copy_field *copy_ptr = copy; copy_ptr != copy_end; copy_ptr++) {
19091
1/2
✓ Branch 0 taken 9342019 times.
✗ Branch 1 not taken.
9342019 copy_ptr->invoke_do_copy();
19092 }
19093
3/4
✓ Branch 0 taken 3208657 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 3208620 times.
3208657 if (thd->is_error()) {
19094 37 error = 1;
19095 37 break;
19096 }
19097
19098 /*
19099 Iterate through all generated columns and all new columns which have
19100 generated defaults and evaluate their values. This needs to happen
19101 after copying values for old columns and storing default values for
19102 new columns without generated defaults, as generated values might
19103 depend on these values.
19104 OTOH generated columns/generated defaults need to be processed in
19105 the order in which their columns are present in table as generated
19106 values are allowed to depend on each other as long as there are no
19107 forward references (i.e. references to other columns with generated
19108 values which come later in the table).
19109 */
19110
2/2
✓ Branch 0 taken 1475 times.
✓ Branch 1 taken 3208577 times.
3210052 for (ptr = gen_fields; ptr != gen_fields_end; ptr++) {
19111 Item *expr_item;
19112
2/2
✓ Branch 0 taken 1271 times.
✓ Branch 1 taken 204 times.
1475 if ((*ptr)->is_gcol()) {
19113 1271 expr_item = (*ptr)->gcol_info->expr_item;
19114 } else {
19115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 204 times.
204 assert((*ptr)->has_insert_default_general_value_expression());
19116 204 expr_item = (*ptr)->m_default_val_expr->expr_item;
19117 }
19118
1/2
✓ Branch 0 taken 1475 times.
✗ Branch 1 not taken.
1475 expr_item->save_in_field(*ptr, false);
19119
3/4
✓ Branch 0 taken 1475 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
✓ Branch 3 taken 1432 times.
1475 if (thd->is_error()) {
19120 43 error = 1;
19121 43 break;
19122 }
19123 }
19124
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 3208577 times.
3208620 if (error) break;
19125
19126
1/2
✓ Branch 0 taken 3208576 times.
✗ Branch 1 not taken.
3208577 error = invoke_table_check_constraints(thd, to);
19127
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 3208562 times.
3208576 if (error) break;
19128
19129
1/2
✓ Branch 0 taken 3208562 times.
✗ Branch 1 not taken.
3208562 error = to->file->ha_write_row(to->record[0]);
19130 3208562 to->autoinc_field_has_explicit_non_null_value = false;
19131
2/2
✓ Branch 0 taken 843 times.
✓ Branch 1 taken 3207719 times.
3208562 if (error) {
19132
3/4
✓ Branch 0 taken 843 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 839 times.
843 if (!to->file->is_ignorable_error(error)) {
19133 /* Not a duplicate key error. */
19134
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 to->file->print_error(error, MYF(0));
19135 4 break;
19136
2/4
✓ Branch 0 taken 839 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 839 times.
✗ Branch 3 not taken.
839 } else if (!to->file->continue_partition_copying_on_error(error)) {
19137 /* Report duplicate key error. */
19138
1/2
✓ Branch 0 taken 839 times.
✗ Branch 1 not taken.
839 uint key_nr = to->file->get_dup_key(error);
19139
2/2
✓ Branch 0 taken 836 times.
✓ Branch 1 taken 3 times.
839 if ((int)key_nr >= 0) {
19140
1/2
✓ Branch 0 taken 836 times.
✗ Branch 1 not taken.
836 const char *err_msg = ER_THD(thd, ER_DUP_ENTRY_WITH_KEY_NAME);
19141
6/6
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 801 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 34 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 835 times.
836 if (key_nr == 0 && (to->key_info[0].key_part[0].field->is_flag_set(
19142 AUTO_INCREMENT_FLAG)))
19143
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 err_msg = ER_THD(thd, ER_DUP_ENTRY_AUTOINCREMENT_CASE);
19144
1/2
✓ Branch 0 taken 836 times.
✗ Branch 1 not taken.
836 print_keydup_error(
19145 836 to, key_nr == MAX_KEY ? nullptr : &to->key_info[key_nr], err_msg,
19146
1/2
✓ Branch 0 taken 836 times.
✗ Branch 1 not taken.
836 MYF(0), from->s->table_name.str);
19147 } else
19148
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 to->file->print_error(error, MYF(0));
19149 839 break;
19150 }
19151 } else {
19152
3/4
✓ Branch 0 taken 3207536 times.
✓ Branch 1 taken 182 times.
✓ Branch 2 taken 3207538 times.
✗ Branch 3 not taken.
3207719 DEBUG_SYNC(thd, "copy_data_between_tables_before");
19153 3207720 found_count++;
19154 3207720 mysql_stage_set_work_completed(psi, found_count);
19155 }
19156 3207718 thd->get_stmt_da()->inc_current_row_for_condition();
19157 }
19158 20470 iterator.reset();
19159
1/2
✓ Branch 0 taken 20470 times.
✗ Branch 1 not taken.
20470 free_io_cache(from);
19160
19161
3/4
✓ Branch 0 taken 20277 times.
✓ Branch 1 taken 193 times.
✓ Branch 2 taken 20277 times.
✗ Branch 3 not taken.
20470 DEBUG_SYNC(thd, "after_copy_data_between_tables");
19162
19163
3/8
✓ Branch 0 taken 20470 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 20470 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 20470 times.
20470 if (to->file->ha_end_bulk_insert() && error <= 0) {
19164 to->file->print_error(my_errno(), MYF(0));
19165 error = 1;
19166 }
19167
19168
4/6
✓ Branch 0 taken 20470 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 20468 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
20470 DBUG_EXECUTE_IF("crash_copy_before_commit", DBUG_SUICIDE(););
19169
19170 /* This code commits the entire transaction (both trans_commit_stmt()
19171 and trans_commit_implicit()) for engines that don't support atomic DDL
19172 and for all temporary tables(independent of engine type)
19173
19174 When expanded fast index creation is enabled, after copy data stage,
19175 there are inplace alters to add removed secondary indexes. Thus we
19176 need to commit the transaction again. A full commit here would make
19177 all future trans_commit_stmt() and trans_commit_implicit() to be dummy
19178 and we would leave transaction open.
19179
19180 With 8.0, this code looks irrevelant for temporary tables but we play
19181 safe and disable intermediate commit only for temporary tables when
19182 expanded fast index creation is enabled */
19183 48994 if ((!(to->file->ht->flags & HTON_SUPPORTS_ATOMIC_DDL) ||
19184
7/8
✓ Branch 0 taken 8058 times.
✓ Branch 1 taken 12410 times.
✓ Branch 2 taken 1050 times.
✓ Branch 3 taken 7008 times.
✓ Branch 4 taken 1045 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 20468 times.
✗ Branch 7 not taken.
33923 (from->s->tmp_table && !expand_fast_index_creation)) &&
19185
2/4
✓ Branch 0 taken 13455 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13455 times.
13455 mysql_trans_commit_alter_copy_data(thd))
19186 error = 1;
19187
19188 20468 err:
19189
1/2
✓ Branch 0 taken 20469 times.
✗ Branch 1 not taken.
20469 destroy_array(copy, to->s->fields);
19190 20469 thd->variables.sql_mode = save_sql_mode;
19191
1/2
✓ Branch 0 taken 20469 times.
✗ Branch 1 not taken.
20469 free_io_cache(from);
19192 20469 *copied = found_count;
19193 20469 *deleted = delete_count;
19194
1/2
✓ Branch 0 taken 20469 times.
✗ Branch 1 not taken.
20469 to->file->ha_release_auto_increment();
19195
2/4
✓ Branch 0 taken 20469 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 20469 times.
20469 if (to->file->ha_external_lock(thd, F_UNLCK)) error = 1;
19196
5/8
✓ Branch 0 taken 19496 times.
✓ Branch 1 taken 973 times.
✓ Branch 2 taken 19496 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 19496 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 20469 times.
20469 if (error < 0 && to->file->ha_extra(HA_EXTRA_PREPARE_FOR_RENAME)) error = 1;
19197 20469 thd->check_for_truncated_fields = CHECK_FIELD_IGNORE;
19198
2/2
✓ Branch 0 taken 973 times.
✓ Branch 1 taken 19496 times.
20469 return error > 0 ? -1 : 0;
19199 20469 }
19200
19201 /*
19202 Recreates tables by calling mysql_alter_table().
19203
19204 SYNOPSIS
19205 mysql_recreate_table()
19206 thd Thread handler
19207 tables Tables to recreate
19208 table_copy Recreate the table by using ALTER TABLE COPY algorithm
19209
19210 RETURN
19211 Like mysql_alter_table().
19212 */
19213 2132 bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool table_copy) {
19214
1/2
✓ Branch 0 taken 2132 times.
✗ Branch 1 not taken.
2132 HA_CREATE_INFO create_info;
19215
1/2
✓ Branch 0 taken 2132 times.
✗ Branch 1 not taken.
2132 Alter_info alter_info(thd->mem_root);
19216
19217
1/2
✓ Branch 0 taken 2132 times.
✗ Branch 1 not taken.
2132 DBUG_TRACE;
19218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2132 times.
2132 assert(!table_list->next_global);
19219
19220 /* Set lock type which is appropriate for ALTER TABLE. */
19221 2132 table_list->set_lock({TL_READ_NO_INSERT, THR_DEFAULT});
19222 /* Same applies to MDL request. */
19223 2132 table_list->mdl_request.set_type(MDL_SHARED_NO_WRITE);
19224
19225 2132 create_info.row_type = ROW_TYPE_NOT_USED;
19226 2132 create_info.default_table_charset = default_charset_info;
19227 /* Force alter table to recreate table */
19228 2132 alter_info.flags =
19229 (Alter_info::ALTER_CHANGE_COLUMN | Alter_info::ALTER_RECREATE);
19230
19231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2132 times.
2132 if (table_copy)
19232 alter_info.requested_algorithm = Alter_info::ALTER_TABLE_ALGORITHM_COPY;
19233
19234
1/2
✓ Branch 0 taken 2112 times.
✗ Branch 1 not taken.
2132 const bool ret = mysql_alter_table(thd, NullS, NullS, &create_info,
19235 table_list, &alter_info);
19236 2112 return ret;
19237 2112 }
19238
19239 28041 bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
19240 HA_CHECK_OPT *check_opt) {
19241 TABLE_LIST *table;
19242 Item *item;
19243 28041 Protocol *protocol = thd->get_protocol();
19244
1/2
✓ Branch 0 taken 28041 times.
✗ Branch 1 not taken.
28041 DBUG_TRACE;
19245
19246 /*
19247 CHECKSUM TABLE returns results and rollbacks statement transaction,
19248 so it should not be used in stored function or trigger.
19249 */
19250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28041 times.
28041 assert(!thd->in_sub_stmt);
19251
19252 28041 mem_root_deque<Item *> field_list(thd->mem_root);
19253
3/6
✓ Branch 0 taken 28041 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28041 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28041 times.
✗ Branch 5 not taken.
28041 field_list.push_back(item = new Item_empty_string("Table", NAME_LEN * 2));
19254 28041 item->set_nullable(true);
19255
2/4
✓ Branch 0 taken 28041 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28041 times.
✗ Branch 3 not taken.
84123 field_list.push_back(item = new Item_int(NAME_STRING("Checksum"), (longlong)1,
19256
1/2
✓ Branch 0 taken 28041 times.
✗ Branch 1 not taken.
56082 MY_INT64_NUM_DECIMAL_DIGITS));
19257 28041 item->set_nullable(true);
19258
2/4
✓ Branch 0 taken 28041 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28041 times.
28041 if (thd->send_result_metadata(field_list,
19259 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
19260 return true;
19261
19262 /*
19263 Close all temporary tables which were pre-open to simplify
19264 privilege checking. Clear all references to closed tables.
19265 */
19266
1/2
✓ Branch 0 taken 28041 times.
✗ Branch 1 not taken.
28041 close_thread_tables(thd);
19267
2/2
✓ Branch 0 taken 722336 times.
✓ Branch 1 taken 28041 times.
750377 for (table = tables; table; table = table->next_local) table->table = nullptr;
19268
19269 /* Open one table after the other to keep lock time as short as possible. */
19270
2/2
✓ Branch 0 taken 722336 times.
✓ Branch 1 taken 28041 times.
750377 for (table = tables; table; table = table->next_local) {
19271 char table_name[NAME_LEN * 2 + 2];
19272 TABLE *t;
19273 TABLE_LIST *save_next_global;
19274
19275
1/2
✓ Branch 0 taken 722336 times.
✗ Branch 1 not taken.
722336 strxmov(table_name, table->db, ".", table->table_name, NullS);
19276
19277 /* Remember old 'next' pointer and break the list. */
19278 722336 save_next_global = table->next_global;
19279 722336 table->next_global = nullptr;
19280 722336 table->set_lock({TL_READ, THR_DEFAULT});
19281 /* Allow to open real tables only. */
19282 722336 table->required_type = dd::enum_table_type::BASE_TABLE;
19283
19284
4/6
✓ Branch 0 taken 722336 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 722336 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 722328 times.
1444672 if (open_temporary_tables(thd, table) ||
19285
3/4
✓ Branch 0 taken 722336 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 722328 times.
722336 open_and_lock_tables(thd, table, 0)) {
19286 8 t = nullptr;
19287 } else
19288 722328 t = table->table;
19289
19290 722336 table->next_global = save_next_global;
19291
19292
1/2
✓ Branch 0 taken 722336 times.
✗ Branch 1 not taken.
722336 protocol->start_row();
19293
1/2
✓ Branch 0 taken 722336 times.
✗ Branch 1 not taken.
722336 protocol->store(table_name, system_charset_info);
19294
19295
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 722328 times.
722336 if (!t) {
19296 /* Table didn't exist */
19297
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 protocol->store_null();
19298 } else {
19299
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 722325 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 722326 times.
722331 if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
19300
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 !(check_opt->flags & T_EXTEND))
19301
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 protocol->store((ulonglong)t->file->checksum());
19302
4/4
✓ Branch 0 taken 722325 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 722324 times.
1444651 else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
19303
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 722323 times.
722325 (check_opt->flags & T_QUICK))
19304
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 protocol->store_null();
19305 else {
19306 /* calculating table's checksum */
19307 722324 ha_checksum crc = 0;
19308 722324 uchar null_mask = 256 - (1 << t->s->last_null_bit_pos);
19309
19310
1/2
✓ Branch 0 taken 722324 times.
✗ Branch 1 not taken.
722324 t->use_all_columns();
19311
19312
2/4
✓ Branch 0 taken 722324 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 722324 times.
722324 if (t->file->ha_rnd_init(true))
19313 protocol->store_null();
19314 else {
19315 for (;;) {
19316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 131759229 times.
131759229 if (thd->killed) {
19317 /*
19318 we've been killed; let handler clean up, and remove the
19319 partial current row from the recordset (embedded lib)
19320 */
19321 t->file->ha_rnd_end();
19322 protocol->abort_row();
19323 goto err;
19324 }
19325 131759229 ha_checksum row_crc = 0;
19326
1/2
✓ Branch 0 taken 131759229 times.
✗ Branch 1 not taken.
131759229 int error = t->file->ha_rnd_next(t->record[0]);
19327
2/2
✓ Branch 0 taken 1247606 times.
✓ Branch 1 taken 130511623 times.
131759229 if (unlikely(error)) {
19328
2/2
✓ Branch 0 taken 525282 times.
✓ Branch 1 taken 722324 times.
1247606 if (error == HA_ERR_RECORD_DELETED) continue;
19329 722324 break;
19330 }
19331
2/2
✓ Branch 0 taken 3231439 times.
✓ Branch 1 taken 127280184 times.
130511623 if (t->s->null_bytes) {
19332 /* fix undefined null bits */
19333 3231439 t->record[0][t->s->null_bytes - 1] |= null_mask;
19334
2/2
✓ Branch 0 taken 1573239 times.
✓ Branch 1 taken 1658200 times.
3231439 if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
19335 1573239 t->record[0][0] |= 1;
19336
19337
1/2
✓ Branch 0 taken 3231439 times.
✗ Branch 1 not taken.
3231439 row_crc = checksum_crc32(row_crc, t->record[0], t->s->null_bytes);
19338 }
19339
19340
2/2
✓ Branch 0 taken 375369488 times.
✓ Branch 1 taken 130511623 times.
505881111 for (uint i = 0; i < t->s->fields; i++) {
19341 375369488 Field *f = t->field[i];
19342
19343 /*
19344 BLOB and VARCHAR have pointers in their field, we must convert
19345 to string; GEOMETRY and JSON are implemented on top of BLOB.
19346 BIT may store its data among NULL bits, convert as well.
19347 */
19348
3/4
✓ Branch 0 taken 375369488 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 60912908 times.
✓ Branch 3 taken 314456580 times.
375369488 switch (f->type()) {
19349 60912908 case MYSQL_TYPE_BLOB:
19350 case MYSQL_TYPE_VARCHAR:
19351 case MYSQL_TYPE_GEOMETRY:
19352 case MYSQL_TYPE_JSON:
19353 case MYSQL_TYPE_BIT: {
19354 60912908 String tmp;
19355
1/2
✓ Branch 0 taken 60912908 times.
✗ Branch 1 not taken.
60912908 f->val_str(&tmp);
19356 row_crc =
19357
1/2
✓ Branch 0 taken 60912908 times.
✗ Branch 1 not taken.
60912908 checksum_crc32(row_crc, (uchar *)tmp.ptr(), tmp.length());
19358 60912908 break;
19359 60912908 }
19360 314456580 default:
19361 row_crc =
19362
2/4
✓ Branch 0 taken 314456580 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 314456580 times.
✗ Branch 3 not taken.
314456580 checksum_crc32(row_crc, f->field_ptr(), f->pack_length());
19363 314456580 break;
19364 }
19365 }
19366
19367 130511623 crc += row_crc;
19368 131036905 }
19369
1/2
✓ Branch 0 taken 722324 times.
✗ Branch 1 not taken.
722324 protocol->store((ulonglong)crc);
19370
1/2
✓ Branch 0 taken 722324 times.
✗ Branch 1 not taken.
722324 t->file->ha_rnd_end();
19371 }
19372 }
19373
1/2
✓ Branch 0 taken 722328 times.
✗ Branch 1 not taken.
722328 trans_rollback_stmt(thd);
19374
1/2
✓ Branch 0 taken 722328 times.
✗ Branch 1 not taken.
722328 close_thread_tables(thd);
19375 }
19376
19377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 722336 times.
722336 if (thd->transaction_rollback_request) {
19378 /*
19379 If transaction rollback was requested we honor it. To do this we
19380 abort statement and return error as not only CHECKSUM TABLE is
19381 rolled back but the whole transaction in which it was used.
19382 */
19383 protocol->abort_row();
19384 goto err;
19385 }
19386
19387 /* Hide errors from client. Return NULL for problematic tables instead. */
19388
1/2
✓ Branch 0 taken 722336 times.
✗ Branch 1 not taken.
722336 thd->clear_error();
19389
19390
2/4
✓ Branch 0 taken 722336 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 722336 times.
722336 if (protocol->end_row()) goto err;
19391 }
19392
19393
1/2
✓ Branch 0 taken 28041 times.
✗ Branch 1 not taken.
28041 my_eof(thd);
19394 28041 return false;
19395
19396 err:
19397 return true;
19398 28041 }
19399
19400 /**
19401 @brief Check if the table can be created in the specified storage engine.
19402
19403 Checks if the storage engine is enabled and supports the given table
19404 type (e.g. normal, temporary, system). May do engine substitution
19405 if the requested engine does not support temporary tables.
19406
19407 @param db_name Database name.
19408 @param table_name Name of table to be created.
19409 @param create_info Create info from parser, including engine.
19410
19411 @retval true Engine not available/supported, error has been reported.
19412 @retval false Engine available/supported.
19413 */
19414 851226 static bool check_engine(THD *thd, const char *db_name, const char *table_name,
19415 HA_CREATE_INFO *create_info,
19416 const Alter_info *alter_info) {
19417
1/2
✓ Branch 0 taken 851243 times.
✗ Branch 1 not taken.
851226 DBUG_TRACE;
19418 851243 handlerton **new_engine = &create_info->db_type;
19419 851243 handlerton *req_engine = *new_engine;
19420
19421
4/6
✓ Branch 0 taken 218 times.
✓ Branch 1 taken 851025 times.
✓ Branch 2 taken 218 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 218 times.
✗ Branch 5 not taken.
851243 if (enforce_storage_engine && !opt_initialize && !opt_noacl) {
19422 /*
19423 Storage engine enforcement must be forbidden:
19424 1. for "OPTIMIZE TABLE" statements.
19425 2. for "ALTER TABLE" statements without explicit "... ENGINE=xxx" part
19426 3. Transactional data dictionary (DD) tables
19427 */
19428 218 bool no_substitution = (!is_engine_substitution_allowed(thd));
19429
19430 bool enforcement_forbidden =
19431 252 ((thd->lex->sql_command == SQLCOM_ALTER_TABLE) &&
19432
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 12 times.
34 (create_info->used_fields & HA_CREATE_USED_ENGINE) == 0) ||
19433
2/2
✓ Branch 0 taken 202 times.
✓ Branch 1 taken 4 times.
206 (thd->lex->sql_command == SQLCOM_OPTIMIZE) ||
19434
8/16
✓ Branch 0 taken 202 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 202 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 202 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 202 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 32 times.
✓ Branch 9 taken 170 times.
✓ Branch 10 taken 202 times.
✓ Branch 11 taken 16 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
420 dd::get_dictionary()->is_dd_table_name(db_name, table_name)
19435 // Allow creation of the new redo log table
19436
6/6
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 184 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 28 times.
✓ Branch 4 taken 202 times.
✓ Branch 5 taken 16 times.
436 || (strcmp(db_name, "performance_schema") == 0);
19437
19438
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 173 times.
218 if (!enforcement_forbidden) {
19439
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 handlerton *enf_engine = ha_enforce_handlerton(thd);
19440
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (enf_engine) {
19441
4/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 5 times.
28 if (enf_engine != *new_engine && no_substitution) {
19442
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 const char *engine_name = ha_resolve_storage_engine_name(req_engine);
19443
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), engine_name, engine_name);
19444 9 return true;
19445 }
19446 19 *new_engine = enf_engine;
19447 }
19448 }
19449 }
19450
19451 /*
19452 Check, if the given table name is system table, and if the storage engine
19453 does supports it.
19454 */
19455
4/4
✓ Branch 0 taken 557851 times.
✓ Branch 1 taken 293366 times.
✓ Branch 2 taken 85 times.
✓ Branch 3 taken 851150 times.
1409086 if ((create_info->used_fields & HA_CREATE_USED_ENGINE) &&
19456
3/4
✓ Branch 0 taken 557869 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85 times.
✓ Branch 3 taken 557784 times.
557851 !ha_check_if_supported_system_table(*new_engine, db_name, table_name)) {
19457
2/4
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85 times.
✗ Branch 3 not taken.
85 my_error(ER_UNSUPPORTED_ENGINE, MYF(0),
19458 ha_resolve_storage_engine_name(*new_engine), db_name, table_name);
19459 85 *new_engine = nullptr;
19460 85 return true;
19461 }
19462 /*
19463 Check if the given table has compressed columns, and if the storage engine
19464 does support it.
19465 */
19466 851150 partition_info *part_info = thd->work_part_info;
19467 bool check_compressed_columns =
19468
2/2
✓ Branch 0 taken 843031 times.
✓ Branch 1 taken 8119 times.
1694177 part_info == 0 &&
19469
2/2
✓ Branch 0 taken 709636 times.
✓ Branch 1 taken 133395 times.
843031 !(create_info->db_type->partition_flags &&
19470
2/4
✓ Branch 0 taken 709632 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 709633 times.
✗ Branch 3 not taken.
709636 (create_info->db_type->partition_flags() & HA_USE_AUTO_PARTITION));
19471
19472
7/8
✓ Branch 0 taken 843029 times.
✓ Branch 1 taken 8117 times.
✓ Branch 2 taken 843032 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 292 times.
✓ Branch 5 taken 842740 times.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 851139 times.
851438 if (check_compressed_columns && alter_info->has_compressed_columns() &&
19473
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 282 times.
292 !ha_check_storage_engine_flag(*new_engine,
19474 HTON_SUPPORTS_COMPRESSED_COLUMNS)) {
19475
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
19476 ha_resolve_storage_engine_name(*new_engine), "COMPRESSED COLUMNS");
19477 10 *new_engine = 0;
19478 10 return true;
19479 }
19480
19481 // The storage engine must support secondary engines.
19482
2/2
✓ Branch 0 taken 211 times.
✓ Branch 1 taken 850928 times.
851139 if (create_info->used_fields & HA_CREATE_USED_SECONDARY_ENGINE &&
19483
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 210 times.
211 !((*new_engine)->flags & HTON_SUPPORTS_SECONDARY_ENGINE)) {
19484
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SECONDARY_ENGINE");
19485 1 return true;
19486 }
19487
19488 // The storage engine must support encryption.
19489
2/2
✓ Branch 0 taken 94315 times.
✓ Branch 1 taken 756823 times.
851138 if (create_info->encrypt_type.str) {
19490 94315 bool encryption_request_type = false;
19491 94315 dd::String_type encrypt_type;
19492
1/2
✓ Branch 0 taken 94326 times.
✗ Branch 1 not taken.
94325 encrypt_type.assign(create_info->encrypt_type.str,
19493 create_info->encrypt_type.length);
19494
1/2
✓ Branch 0 taken 94327 times.
✗ Branch 1 not taken.
94326 encryption_request_type = is_encrypted(encrypt_type);
19495
2/2
✓ Branch 0 taken 7969 times.
✓ Branch 1 taken 86358 times.
94327 if (encryption_request_type &&
19496
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 7935 times.
7969 !((*new_engine)->flags & HTON_SUPPORTS_TABLE_ENCRYPTION)) {
19497
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "ENCRYPTION");
19498 34 return true;
19499 }
19500
2/2
✓ Branch 0 taken 94293 times.
✓ Branch 1 taken 34 times.
94327 }
19501
19502 851116 return false;
19503 851255 }
19504
19505 /**
19506 Helper method to generate check constraint name.
19507
19508 @param thd Thread handle.
19509 @param table_name Table name.
19510 @param ordinal_number Ordinal number of the generated name.
19511 @param[out] name LEX_STRING instance to hold the
19512 generated check constraint name.
19513 @param skip_validation Skip generated name validation.
19514 */
19515 320 static bool generate_check_constraint_name(THD *thd, const char *table_name,
19516 uint ordinal_number,
19517 LEX_STRING &name,
19518 bool skip_validation) {
19519 // Allocate memory for name.
19520 320 size_t generated_name_len =
19521 320 strlen(table_name) + sizeof(dd::CHECK_CONSTRAINT_NAME_SUBSTR) + 11 + 1;
19522 320 name.str = (char *)thd->mem_root->Alloc(generated_name_len);
19523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 320 times.
320 if (name.str == nullptr) return true; // OOM
19524
19525 // Prepare name for check constraint.
19526 320 sprintf(name.str, "%s%s%u", table_name, dd::CHECK_CONSTRAINT_NAME_SUBSTR,
19527 ordinal_number);
19528 320 name.length = strlen(name.str);
19529
19530 // Validate check constraint name.
19531
2/2
✓ Branch 0 taken 281 times.
✓ Branch 1 taken 39 times.
601 if (!skip_validation &&
19532
5/6
✓ Branch 0 taken 281 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 279 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 318 times.
601 check_string_char_length(to_lex_cstring(name), "", NAME_CHAR_LEN,
19533 system_charset_info, true)) {
19534 2 my_error(ER_TOO_LONG_IDENT, MYF(0), name.str);
19535 2 return true;
19536 }
19537
19538 318 return false;
19539 }
19540
19541 /**
19542 Helper method to create MDL_request for check constraint names. Check
19543 constraint names are case insensitive. Hence names are lowercased
19544 in MDL_request and pushed to MDL_request_list.
19545
19546 @param thd Thread handle.
19547 @param db Database name.
19548 @param cc_name Check constraint name.
19549 @param[out] cc_mdl_request_list MDL request list.
19550
19551 @retval false Success.
19552 @retval true Failure.
19553 */
19554 4296 static bool push_check_constraint_mdl_request_to_list(
19555 THD *thd, const char *db, const char *cc_name,
19556 MDL_request_list &cc_mdl_request_list) {
19557
3/6
✓ Branch 0 taken 4296 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4296 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4296 times.
✗ Branch 5 not taken.
4296 assert(thd != nullptr && db != nullptr && cc_name != nullptr);
19558
19559 /*
19560 Check constraint names are case insensitive. Hence lowercasing names for
19561 MDL locking.
19562 */
19563 char lc_cc_name[NAME_LEN + 1];
19564
1/2
✓ Branch 0 taken 4296 times.
✗ Branch 1 not taken.
4296 strmake(lc_cc_name, cc_name, NAME_LEN);
19565
1/2
✓ Branch 0 taken 4296 times.
✗ Branch 1 not taken.
4296 my_casedn_str(system_charset_info, lc_cc_name);
19566
19567
1/2
✓ Branch 0 taken 4296 times.
✗ Branch 1 not taken.
4296 MDL_request *mdl_request = new (thd->mem_root) MDL_request;
19568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4296 times.
4296 if (mdl_request == nullptr) return true; // OOM
19569
1/2
✓ Branch 0 taken 4296 times.
✗ Branch 1 not taken.
4296 MDL_REQUEST_INIT(mdl_request, MDL_key::CHECK_CONSTRAINT, db, lc_cc_name,
19570 MDL_EXCLUSIVE, MDL_STATEMENT);
19571
1/2
✓ Branch 0 taken 4296 times.
✗ Branch 1 not taken.
4296 cc_mdl_request_list.push_front(mdl_request);
19572
19573 4296 return false;
19574 }
19575
19576 670339 bool prepare_check_constraints_for_create(THD *thd, const char *db_name,
19577 const char *table_name,
19578 Alter_info *alter_info) {
19579
1/2
✓ Branch 0 taken 670344 times.
✗ Branch 1 not taken.
670339 DBUG_TRACE;
19580
1/2
✓ Branch 0 taken 670343 times.
✗ Branch 1 not taken.
670344 MDL_request_list cc_mdl_request_list;
19581 670343 uint cc_max_generated_number = 0;
19582
19583 /*
19584 Do not process check constraint specification list if master is on version
19585 not supporting check constraints feature.
19586 */
19587
3/4
✓ Branch 0 taken 670339 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 670312 times.
670343 if (is_slave_with_master_without_check_constraints_support(thd)) {
19588
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 alter_info->check_constraint_spec_list.clear();
19589 27 return false;
19590 }
19591
19592
3/4
✓ Branch 0 taken 670316 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 843 times.
✓ Branch 3 taken 670256 times.
671095 for (auto &cc_spec : alter_info->check_constraint_spec_list) {
19593 // If check constraint name is omitted then generate name.
19594
2/2
✓ Branch 0 taken 219 times.
✓ Branch 1 taken 624 times.
843 if (cc_spec->name.length == 0) {
19595
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 218 times.
219 if (generate_check_constraint_name(
19596
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 thd, table_name, ++cc_max_generated_number, cc_spec->name, false))
19597 1 return true;
19598 }
19599
19600 // Pre-validate check constraint.
19601
3/4
✓ Branch 0 taken 842 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 59 times.
✓ Branch 3 taken 783 times.
842 if (cc_spec->pre_validate()) return true;
19602
19603 // Create MDL request for the check constraint.
19604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 783 times.
783 if (push_check_constraint_mdl_request_to_list(
19605
1/2
✓ Branch 0 taken 783 times.
✗ Branch 1 not taken.
783 thd, db_name, cc_spec->name.str, cc_mdl_request_list))
19606 return true;
19607 }
19608
19609 // Make sure fields used by the check constraint exists in the create list.
19610 670256 mem_root_deque<Item_field *> fields(thd->mem_root);
19611
3/4
✓ Branch 0 taken 670256 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 776 times.
✓ Branch 3 taken 670253 times.
671025 for (auto &cc_spec : alter_info->check_constraint_spec_list) {
19612
1/2
✓ Branch 0 taken 776 times.
✗ Branch 1 not taken.
776 cc_spec->check_expr->walk(&Item::collect_item_field_processor,
19613 enum_walk::POSTFIX, (uchar *)&fields);
19614
19615 Create_field *cur_fld;
19616
1/2
✓ Branch 0 taken 776 times.
✗ Branch 1 not taken.
776 List_iterator<Create_field> create_fields_it(alter_info->create_list);
19617
7/12
✓ Branch 0 taken 776 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 776 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1350 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1347 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2123 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1350 times.
✓ Branch 11 taken 773 times.
2123 for (Item_field *cur_item_fld : fields) {
19618
3/4
✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1349 times.
1350 if (cur_item_fld->type() != Item::FIELD_ITEM) continue;
19619
19620
2/2
✓ Branch 0 taken 2838 times.
✓ Branch 1 taken 3 times.
2841 while ((cur_fld = create_fields_it++)) {
19621
3/4
✓ Branch 0 taken 2838 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1346 times.
✓ Branch 3 taken 1492 times.
2838 if (!my_strcasecmp(system_charset_info, cur_item_fld->field_name,
19622 cur_fld->field_name))
19623 1346 break;
19624 }
19625 1349 create_fields_it.rewind();
19626
19627
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1346 times.
1349 if (cur_fld == nullptr) {
19628 3 my_error(ER_CHECK_CONSTRAINT_REFERS_UNKNOWN_COLUMN, MYF(0),
19629
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 cc_spec->name.str, cur_item_fld->field_name);
19630 3 return true;
19631 }
19632 }
19633
1/2
✓ Branch 0 taken 773 times.
✗ Branch 1 not taken.
773 fields.clear();
19634 }
19635
19636
3/4
✓ Branch 0 taken 606466 times.
✓ Branch 1 taken 63783 times.
✓ Branch 2 taken 606471 times.
✗ Branch 3 not taken.
670253 DEBUG_SYNC(thd, "before_acquiring_lock_on_check_constraints");
19637
2/4
✓ Branch 0 taken 670251 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 670251 times.
670254 if (thd->mdl_context.acquire_locks(&cc_mdl_request_list,
19638 thd->variables.lock_wait_timeout))
19639 return true;
19640
3/4
✓ Branch 0 taken 606470 times.
✓ Branch 1 taken 63783 times.
✓ Branch 2 taken 606472 times.
✗ Branch 3 not taken.
670251 DEBUG_SYNC(thd, "after_acquiring_lock_on_check_constraints");
19641
19642 670255 return false;
19643 670345 }
19644
19645 /**
19646 Method to prepare check constraints for the CREATE TABLE LIKE operation.
19647 If check constraints are defined on the source table then check constraints
19648 specifications are prepared for the table being created from it. To
19649 avoid name conflicts, names are generated for all the check constraints
19650 prepared for the table being created.
19651
19652
19653 @param thd Thread handle.
19654 @param src_table TABLE_LIST instance for source table.
19655 @param target_table TABLE_LIST instance for target table.
19656 @param alter_info Alter_info instance to prepare
19657 list of check constraint spec
19658 for table being created.
19659
19660 @retval false Success.
19661 @retval true Failure.
19662 */
19663 1168 static bool prepare_check_constraints_for_create_like_table(
19664 THD *thd, TABLE_LIST *src_table, TABLE_LIST *target_table,
19665 Alter_info *alter_info) {
19666
1/2
✓ Branch 0 taken 1168 times.
✗ Branch 1 not taken.
1168 DBUG_TRACE;
19667
1/2
✓ Branch 0 taken 1168 times.
✗ Branch 1 not taken.
1168 MDL_request_list cc_mdl_request_list;
19668 1168 uint number = 0;
19669
19670
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1165 times.
1168 if (src_table->table->table_check_constraint_list != nullptr) {
19671
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 3 times.
15 for (auto &table_cc : *src_table->table->table_check_constraint_list) {
19672 Sql_check_constraint_spec *cc_spec =
19673
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 new (thd->mem_root) Sql_check_constraint_spec;
19674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (cc_spec == nullptr) return true; // OOM
19675
19676 // For create like table, all the check constraint names are generated to
19677 // avoid name conflicts.
19678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (generate_check_constraint_name(thd, target_table->table_name,
19679
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 ++number, cc_spec->name, true))
19680 return true;
19681
19682 // check constraint expression.
19683 12 cc_spec->check_expr = table_cc.value_generator()->expr_item;
19684
19685 // Copy check constraint status.
19686 12 cc_spec->is_enforced = table_cc.is_enforced();
19687
19688
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 alter_info->check_constraint_spec_list.push_back(cc_spec);
19689
19690 /*
19691 Create MDL request for check constraint in source table and the
19692 generated check constraint name for target table.
19693 */
19694
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (push_check_constraint_mdl_request_to_list(
19695
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
36 thd, src_table->db, table_cc.name().str, cc_mdl_request_list) ||
19696
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 push_check_constraint_mdl_request_to_list(
19697
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 thd, target_table->db, cc_spec->name.str, cc_mdl_request_list))
19698 return true;
19699 }
19700 }
19701
19702
2/4
✓ Branch 0 taken 1168 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1168 times.
✗ Branch 3 not taken.
1168 DEBUG_SYNC(thd, "before_acquiring_lock_on_check_constraints");
19703
2/4
✓ Branch 0 taken 1168 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1168 times.
1168 if (thd->mdl_context.acquire_locks(&cc_mdl_request_list,
19704 thd->variables.lock_wait_timeout))
19705 return true;
19706
2/4
✓ Branch 0 taken 1168 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1168 times.
✗ Branch 3 not taken.
1168 DEBUG_SYNC(thd, "after_acquiring_lock_on_check_constraints");
19707
19708 1168 return false;
19709 1168 }
19710
19711 /**
19712 Method to prepare check constraints for the ALTER TABLE operation.
19713 Method prepares check constraints specifications from the existing
19714 list of check constraints on the table, appends new check constraints
19715 to list, updates state (enforced/not enforced) and drop any existing
19716 check constraint from the list.
19717
19718 @param thd Thread handle.
19719 @param table TABLE instance of source table.
19720 @param alter_info Alter_info object to prepare
19721 list of check constraint spec
19722 for table being altered.
19723 @param alter_tbl_ctx Runtime context for
19724 ALTER TABLE.
19725
19726 @retval false Success.
19727 @retval true Failure.
19728 */
19729 89527 static bool prepare_check_constraints_for_alter(
19730 THD *thd, const TABLE *table, Alter_info *alter_info,
19731 Alter_table_ctx *alter_tbl_ctx) {
19732
1/2
✓ Branch 0 taken 89527 times.
✗ Branch 1 not taken.
89527 DBUG_TRACE;
19733
1/2
✓ Branch 0 taken 89527 times.
✗ Branch 1 not taken.
89527 MDL_request_list cc_mdl_request_list;
19734
1/2
✓ Branch 0 taken 89527 times.
✗ Branch 1 not taken.
89527 Sql_check_constraint_spec_list new_check_cons_list(thd->mem_root);
19735 89527 uint cc_max_generated_number = 0;
19736 89527 uint table_name_len = strlen(alter_tbl_ctx->table_name);
19737
19738 /*
19739 Do not process check constraint specification list if master is on version
19740 not supporting check constraints feature.
19741 */
19742
3/4
✓ Branch 0 taken 89527 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 89525 times.
89527 if (is_slave_with_master_without_check_constraints_support(thd)) {
19743
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 alter_info->check_constraint_spec_list.clear();
19744 2 return false;
19745 }
19746
19747 1163 auto find_cc_name = [](std::vector<const char *> &names, const char *s) {
19748
1/2
✓ Branch 0 taken 1163 times.
✗ Branch 1 not taken.
1163 auto name = find_if(names.begin(), names.end(), [s](const char *cc_name) {
19749 135 return !my_strcasecmp(system_charset_info, s, cc_name);
19750 });
19751
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 1099 times.
1163 return (name != names.end()) ? *name : nullptr;
19752 };
19753
19754 /*
19755 List of check constraint names. Used after acquiring MDL locks on final list
19756 of check constraints to verify if check constraint names conflict with
19757 existing check constraint names.
19758 */
19759 89525 std::vector<const char *> new_cc_names;
19760
19761 /*
19762 Handle check constraint specifications marked for drop.
19763
19764 Prepare list of check constraint names (Pointer to the constraint name in
19765 Alter_drop instances) marked for drop. List is used to skip constraints
19766 while preparing specification list from existing check constraints and
19767 while adding new check constraints with the same name.
19768 */
19769 89525 std::vector<const char *> dropped_cc_names;
19770
3/4
✓ Branch 0 taken 89525 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12203 times.
✓ Branch 3 taken 89522 times.
101725 for (const Alter_drop *drop : alter_info->drop_list) {
19771
2/2
✓ Branch 0 taken 12155 times.
✓ Branch 1 taken 48 times.
12203 if (drop->type != Alter_drop::CHECK_CONSTRAINT) continue;
19772
19773 48 bool cc_found = false;
19774
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 1 times.
48 if (table->table_check_constraint_list != nullptr) {
19775 37 for (Sql_table_check_constraint &table_cc :
19776
3/4
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 82 times.
✓ Branch 3 taken 2 times.
84 *table->table_check_constraint_list) {
19777
3/4
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 37 times.
82 if (!my_strcasecmp(system_charset_info, table_cc.name().str,
19778 drop->name)) {
19779
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 dropped_cc_names.push_back(drop->name);
19780 45 cc_found = true;
19781 45 break;
19782 }
19783 }
19784 }
19785
19786
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 45 times.
48 if (!cc_found) {
19787
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_CHECK_CONSTRAINT_NOT_FOUND, MYF(0), drop->name);
19788 3 return true;
19789 }
19790 }
19791
19792 /*
19793 Auto-drop check constraint: If check constraint refers to only one column
19794 and that column is marked for drop then drop
19795 check constraint too.
19796 Check constraints marked for auto-drop are added to list of check constraint
19797 (dropped_cc_names) to be dropped.
19798 */
19799
2/2
✓ Branch 0 taken 778 times.
✓ Branch 1 taken 88744 times.
89522 if (table->table_check_constraint_list != nullptr) {
19800
3/4
✓ Branch 0 taken 778 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 488 times.
✓ Branch 3 taken 778 times.
1266 for (const Alter_drop *drop : alter_info->drop_list) {
19801
2/2
✓ Branch 0 taken 172 times.
✓ Branch 1 taken 316 times.
488 if (drop->type == Alter_drop::COLUMN) {
19802 178 for (Sql_table_check_constraint &table_cc :
19803
3/4
✓ Branch 0 taken 172 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 178 times.
✓ Branch 3 taken 172 times.
350 *table->table_check_constraint_list) {
19804
3/4
✓ Branch 0 taken 178 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 170 times.
178 if (check_constraint_expr_refers_to_only_column(
19805 178 table_cc.value_generator()->expr_item, drop->name))
19806
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 dropped_cc_names.push_back(table_cc.name().str);
19807 }
19808 }
19809 }
19810 }
19811
19812 /*
19813 Prepare check constraint specification for the existing check constraints on
19814 the table.
19815
19816 * Skip check constraint specification marked for drop.
19817
19818 * Get max sequence number for generated names. This is required when
19819 handling new check constraints added to the table.
19820
19821 * If table is renamed, adjust generated check constraint names to use new
19822 table name.
19823
19824 * Create MDL request on all check constraints.
19825 - Also on adjusted check constraint names if table is renamed.
19826 - If database changed then on all check constraints with the new database.
19827 */
19828
2/2
✓ Branch 0 taken 778 times.
✓ Branch 1 taken 88744 times.
89522 if (table->table_check_constraint_list != nullptr) {
19829
3/4
✓ Branch 0 taken 778 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1024 times.
✓ Branch 3 taken 778 times.
1802 for (auto &table_cc : *table->table_check_constraint_list) {
19830 /*
19831 Push MDL_request for the existing check constraint name.
19832 Note: Notice that this also handles case of dropped constraints.
19833 */
19834
2/4
✓ Branch 0 taken 1024 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1024 times.
1024 if (push_check_constraint_mdl_request_to_list(
19835 1024 thd, alter_tbl_ctx->db, table_cc.name().str, cc_mdl_request_list))
19836 return true;
19837
19838 // Skip if constraint is marked for drop.
19839
3/4
✓ Branch 0 taken 1024 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 973 times.
1024 if (find_cc_name(dropped_cc_names, table_cc.name().str) != nullptr)
19840 51 continue;
19841
19842 Sql_check_constraint_spec *cc_spec =
19843
1/2
✓ Branch 0 taken 973 times.
✗ Branch 1 not taken.
973 new (thd->mem_root) Sql_check_constraint_spec;
19844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 973 times.
973 if (cc_spec == nullptr) return true; // OOM
19845
19846
1/2
✓ Branch 0 taken 973 times.
✗ Branch 1 not taken.
973 bool is_generated_name = dd::is_generated_check_constraint_name(
19847 973 alter_tbl_ctx->table_name, table_name_len, table_cc.name().str,
19848 973 table_cc.name().length);
19849 /*
19850 Get number from generated name and update max generated number if
19851 needed.
19852 */
19853
2/2
✓ Branch 0 taken 299 times.
✓ Branch 1 taken 674 times.
973 if (is_generated_name) {
19854 char *end;
19855 uint number =
19856 299 my_strtoull(table_cc.name().str + table_name_len +
19857 299 sizeof(dd::CHECK_CONSTRAINT_NAME_SUBSTR) - 1,
19858 299 &end, 10);
19859
2/2
✓ Branch 0 taken 231 times.
✓ Branch 1 taken 68 times.
299 if (number > cc_max_generated_number) cc_max_generated_number = number;
19860 }
19861
19862 // If generated name and table is renamed then update generated name.
19863
6/6
✓ Branch 0 taken 299 times.
✓ Branch 1 taken 674 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 290 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 964 times.
973 if (is_generated_name && alter_tbl_ctx->is_table_name_changed()) {
19864 char *end;
19865 uint number =
19866 9 my_strtoull(table_cc.name().str + table_name_len +
19867 9 sizeof(dd::CHECK_CONSTRAINT_NAME_SUBSTR) - 1,
19868 9 &end, 10);
19869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (number > cc_max_generated_number) cc_max_generated_number = number;
19870
19871 // Generate new check constraint name.
19872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (generate_check_constraint_name(thd, alter_tbl_ctx->new_name, number,
19873
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 cc_spec->name, true))
19874 return true;
19875 } else {
19876
1/2
✓ Branch 0 taken 964 times.
✗ Branch 1 not taken.
964 lex_string_strmake(thd->mem_root, &cc_spec->name, table_cc.name().str,
19877 964 table_cc.name().length);
19878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 964 times.
964 if (cc_spec->name.str == nullptr) return true; // OOM
19879 }
19880
19881 // check constraint expression.
19882 973 cc_spec->check_expr = table_cc.value_generator()->expr_item;
19883
19884 // Copy check constraint status.
19885 973 cc_spec->is_enforced = table_cc.is_enforced();
19886
19887 // Push check constraint to new list.
19888
1/2
✓ Branch 0 taken 973 times.
✗ Branch 1 not taken.
973 new_check_cons_list.push_back(cc_spec);
19889
19890 /*
19891 If db is changed then push MDL_request on check constraint with new db
19892 name or if table name is changed then push MDL_request on generated
19893 check constraint name.
19894 */
19895
6/6
✓ Branch 0 taken 971 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 959 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 963 times.
1956 if ((alter_tbl_ctx->is_database_changed() ||
19896
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
983 (alter_tbl_ctx->is_table_name_changed() && is_generated_name))) {
19897
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (push_check_constraint_mdl_request_to_list(
19898
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 thd, alter_tbl_ctx->new_db, cc_spec->name.str,
19899 cc_mdl_request_list))
19900 return true;
19901
19902
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 new_cc_names.push_back(cc_spec->name.str);
19903 }
19904 }
19905
19906 /*
19907 Check if any check constraint refers to column(s) being dropped or
19908 renamed.
19909 */
19910
3/4
✓ Branch 0 taken 778 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 744 times.
✓ Branch 3 taken 34 times.
778 if (!new_check_cons_list.empty()) {
19911 // Check if any check constraint refers column(s) being dropped.
19912
4/6
✓ Branch 0 taken 744 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 744 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 741 times.
744 if (std::any_of(
19913 alter_info->drop_list.begin(), alter_info->drop_list.end(),
19914 Check_constraint_column_dependency_checker(new_check_cons_list)))
19915 3 return true;
19916
19917 /*
19918 Check if any check constraint refers column(s) being renamed using
19919 RENAME COLUMN clause.
19920 */
19921
4/6
✓ Branch 0 taken 741 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 741 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 737 times.
741 if (std::any_of(
19922 alter_info->alter_list.begin(), alter_info->alter_list.end(),
19923 Check_constraint_column_dependency_checker(new_check_cons_list)))
19924 4 return true;
19925
19926 /*
19927 Check if any check constraint refers column(s) being renamed using
19928 CHANGE [COLUMN] clause.
19929 */
19930
5/8
✓ Branch 0 taken 737 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 737 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 737 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 736 times.
737 if (std::any_of(
19931 alter_info->create_list.begin(), alter_info->create_list.end(),
19932 Check_constraint_column_dependency_checker(new_check_cons_list)))
19933 1 return true;
19934 }
19935 }
19936
19937 // Update check constraint enforcement state (i.e. enforced or not enforced).
19938
3/4
✓ Branch 0 taken 89514 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 166 times.
✓ Branch 3 taken 89501 times.
89667 for (auto *alter_constraint : alter_info->alter_constraint_enforcement_list) {
19939
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 156 times.
166 if (alter_constraint->type !=
19940 Alter_constraint_enforcement::Type::CHECK_CONSTRAINT)
19941 10 continue;
19942
19943 156 bool cc_found = false;
19944
3/4
✓ Branch 0 taken 156 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 162 times.
✓ Branch 3 taken 13 times.
175 for (auto &cc_spec : new_check_cons_list) {
19945
3/4
✓ Branch 0 taken 162 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 143 times.
✓ Branch 3 taken 19 times.
162 if (!my_strcasecmp(system_charset_info, cc_spec->name.str,
19946 alter_constraint->name)) {
19947 143 cc_found = true;
19948 // Update status.
19949 143 cc_spec->is_enforced = alter_constraint->is_enforced;
19950 143 break;
19951 }
19952 }
19953
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 143 times.
156 if (!cc_found) {
19954
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 my_error(ER_CHECK_CONSTRAINT_NOT_FOUND, MYF(0), alter_constraint->name);
19955 13 return true;
19956 }
19957 }
19958
19959 /*
19960 Handle new check constraints added to the table.
19961
19962 * Generate name if name is not specified.
19963 If table already has check constraints with generated name then use
19964 sequence number generated when handling existing check constraint names.
19965
19966 * pre-validate check constraint.
19967
19968 * Prepare MDL request for new check constraints.
19969 */
19970
3/4
✓ Branch 0 taken 89501 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 140 times.
✓ Branch 3 taken 89500 times.
89640 for (auto &cc_spec : alter_info->check_constraint_spec_list) {
19971 // If check constraint name is omitted then generate name.
19972
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 78 times.
140 if (cc_spec->name.length == 0) {
19973
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 61 times.
62 if (generate_check_constraint_name(thd, alter_tbl_ctx->new_name,
19974 ++cc_max_generated_number,
19975
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 cc_spec->name, false))
19976 1 return true;
19977 }
19978
19979
2/4
✓ Branch 0 taken 139 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 139 times.
139 if (cc_spec->pre_validate()) return true;
19980
19981 // Push check constraint to new list.
19982
1/2
✓ Branch 0 taken 139 times.
✗ Branch 1 not taken.
139 new_check_cons_list.push_back(cc_spec);
19983
19984 // Create MDL request for the check constraint.
19985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
139 if (push_check_constraint_mdl_request_to_list(
19986
1/2
✓ Branch 0 taken 139 times.
✗ Branch 1 not taken.
139 thd, alter_tbl_ctx->new_db, cc_spec->name.str, cc_mdl_request_list))
19987 return true;
19988
19989 /*
19990 We need to check if conflicting constraint name exists for all newly added
19991 constraints. However, we don't need (and it is inconvenient) to do this
19992 if constraint with the same name was dropped by the same ALTER TABLE,
19993 unless old and new constraints belong to different databases (i.e. this
19994 ALTER TABLE also moves table between databases).
19995 */
19996
3/4
✓ Branch 0 taken 139 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
✓ Branch 3 taken 13 times.
278 if (alter_tbl_ctx->is_database_changed() ||
19997
3/4
✓ Branch 0 taken 139 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
✓ Branch 3 taken 13 times.
139 find_cc_name(dropped_cc_names, cc_spec->name.str) == nullptr)
19998
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 new_cc_names.push_back(cc_spec->name.str);
19999 }
20000
20001 /*
20002 Adjust Alter_info::flags.
20003
20004 * Check if final list has any check constraint whose state is changed from
20005 NOT ENFORCED to ENFORCED.
20006
20007 * Check if list has any new check constraints added with ENFORCED state.
20008
20009 * Update Alter_info::flags accordingly.
20010 */
20011 89500 bool final_enforced_state = false;
20012
3/4
✓ Branch 0 taken 89500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1040 times.
✓ Branch 3 taken 89382 times.
90422 for (auto &cc : new_check_cons_list) {
20013 // Check if any of existing constraint is enforced.
20014
2/2
✓ Branch 0 taken 994 times.
✓ Branch 1 taken 46 times.
1040 if (table->table_check_constraint_list != nullptr) {
20015
3/4
✓ Branch 0 taken 994 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2630 times.
✓ Branch 3 taken 980 times.
3610 for (auto &table_cc : *table->table_check_constraint_list) {
20016
1/2
✓ Branch 0 taken 2630 times.
✗ Branch 1 not taken.
2630 if (!my_strcasecmp(system_charset_info, cc->name.str,
20017 924 table_cc.name().str) &&
20018
8/8
✓ Branch 0 taken 924 times.
✓ Branch 1 taken 1706 times.
✓ Branch 2 taken 606 times.
✓ Branch 3 taken 318 times.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 592 times.
✓ Branch 6 taken 14 times.
✓ Branch 7 taken 2616 times.
2630 !table_cc.is_enforced() && cc->is_enforced) {
20019 14 final_enforced_state = true;
20020 14 break;
20021 }
20022 }
20023 }
20024
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1026 times.
1040 if (final_enforced_state) break;
20025
20026 // Check if new constraint is added in enforced state.
20027
3/4
✓ Branch 0 taken 1026 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 349 times.
✓ Branch 3 taken 922 times.
1271 for (auto &new_cc : alter_info->check_constraint_spec_list) {
20028
5/6
✓ Branch 0 taken 349 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 116 times.
✓ Branch 3 taken 233 times.
✓ Branch 4 taken 104 times.
✓ Branch 5 taken 245 times.
465 if (!my_strcasecmp(system_charset_info, cc->name.str, new_cc->name.str) &&
20029
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 12 times.
116 cc->is_enforced) {
20030 104 final_enforced_state = true;
20031 104 break;
20032 }
20033 }
20034
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 922 times.
1026 if (final_enforced_state) break;
20035 }
20036
2/2
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 89382 times.
89500 if (final_enforced_state)
20037 118 alter_info->flags |= Alter_info::ENFORCE_CHECK_CONSTRAINT;
20038 else
20039 89382 alter_info->flags &= ~Alter_info::ENFORCE_CHECK_CONSTRAINT;
20040
20041 /*
20042 Set alter mode for each check constraint specification instance.
20043
20044 For non-temporary table prepare temporary check constraint names. During
20045 ALTER TABLE operation, two versions of table exists and to avoid check
20046 constraint name conflicts temporary(adjusted) names stored for newer
20047 version and alter mode is set. Check constraint names are restored
20048 later in ALTER TABLE operation. MDL request to temporary name is also
20049 created to avoid creation of table with same name by concurrent operation.
20050
20051 * Prepare temporary(adjusted) name for each check constraint specification.
20052
20053 * Set alter mode for each check constraint specification.
20054
20055 * Prepare MDL request for each temporary name.
20056 */
20057
2/2
✓ Branch 0 taken 88320 times.
✓ Branch 1 taken 1180 times.
89500 if (table->s->tmp_table == NO_TMP_TABLE) {
20058 88320 ulong id = 1;
20059
3/4
✓ Branch 0 taken 88320 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1064 times.
✓ Branch 3 taken 88320 times.
89384 for (Sql_check_constraint_spec *cc : new_check_cons_list) {
20060 1064 const int prefix_len = 3; // #cc
20061 1064 const int process_id_len = 20;
20062 1064 const int thread_id_len = 10;
20063 1064 const int id_len = 20;
20064 1064 const int separator_len = 1;
20065 char temp_name_buf[prefix_len + process_id_len + thread_id_len + id_len +
20066 (separator_len * 3) + 1];
20067 1064 snprintf(temp_name_buf, sizeof(temp_name_buf), "#cc_%lu_%u_%lu",
20068 current_pid, thd->thread_id(), id++);
20069
20070 // Create MDL request for the temp check constraint name.
20071
2/4
✓ Branch 0 taken 1064 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1064 times.
1064 if (push_check_constraint_mdl_request_to_list(
20072 thd, alter_tbl_ctx->new_db, temp_name_buf, cc_mdl_request_list))
20073 return true;
20074
20075 1064 cc->is_alter_mode = true;
20076 1064 cc->alias_name.length = strlen(temp_name_buf);
20077 1064 cc->alias_name.str =
20078
1/2
✓ Branch 0 taken 1064 times.
✗ Branch 1 not taken.
1064 strmake_root(thd->mem_root, temp_name_buf, cc->alias_name.length);
20079 }
20080 }
20081
20082 // Acquire MDL lock on all the MDL_request prepared in this method.
20083
3/4
✓ Branch 0 taken 87120 times.
✓ Branch 1 taken 2380 times.
✓ Branch 2 taken 87120 times.
✗ Branch 3 not taken.
89500 DEBUG_SYNC(thd, "before_acquiring_lock_on_check_constraints");
20084
2/4
✓ Branch 0 taken 89500 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 89500 times.
89500 if (thd->mdl_context.acquire_locks(&cc_mdl_request_list,
20085 thd->variables.lock_wait_timeout))
20086 return true;
20087
3/4
✓ Branch 0 taken 87120 times.
✓ Branch 1 taken 2380 times.
✓ Branch 2 taken 87120 times.
✗ Branch 3 not taken.
89500 DEBUG_SYNC(thd, "after_acquiring_lock_on_check_constraints");
20088
20089 /*
20090 Make sure new check constraint names do not conflict with any existing check
20091 constraint names before starting expensive ALTER operation.
20092 */
20093 89500 dd::Schema_MDL_locker mdl_locker(thd);
20094 89500 const dd::Schema *new_schema = nullptr;
20095
1/2
✓ Branch 0 taken 89500 times.
✗ Branch 1 not taken.
89500 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
20096
2/4
✓ Branch 0 taken 89500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 89500 times.
✗ Branch 3 not taken.
179000 if (mdl_locker.ensure_locked(alter_tbl_ctx->new_db) ||
20097
5/12
✓ Branch 0 taken 89500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 89500 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 89500 times.
✓ Branch 6 taken 89500 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 89500 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
179000 thd->dd_client()->acquire(alter_tbl_ctx->new_db, &new_schema))
20098 return true;
20099 89500 bool exists = false;
20100
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 89497 times.
89633 for (auto cc_name : new_cc_names) {
20101
3/6
✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 136 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 136 times.
136 if (thd->dd_client()->check_constraint_exists(*new_schema, cc_name,
20102 &exists))
20103 3 return true;
20104
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 133 times.
136 if (exists) {
20105
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_CHECK_CONSTRAINT_DUP_NAME, MYF(0), cc_name);
20106 3 return true;
20107 }
20108 }
20109
20110
1/2
✓ Branch 0 taken 89497 times.
✗ Branch 1 not taken.
89497 alter_info->check_constraint_spec_list.clear();
20111
1/2
✓ Branch 0 taken 89497 times.
✗ Branch 1 not taken.
89497 alter_info->check_constraint_spec_list.resize(new_check_cons_list.size());
20112
2/4
✓ Branch 0 taken 89497 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 89497 times.
✗ Branch 3 not taken.
89497 std::move(new_check_cons_list.begin(), new_check_cons_list.end(),
20113 alter_info->check_constraint_spec_list.begin());
20114
20115 89497 return false;
20116 89527 }
20117
20118 /**
20119 During alter table operation, check constraints of a new table are marked as
20120 in alter mode. If a table object is stored to the data-dictionary in this
20121 mode then alias name is stored to avoid name conflicts due to two versions
20122 of table objects. dd::Table object of a new table read from the
20123 data-dictionary contains only alias name. So dd::Table object of a new table
20124 is patched up here with the real name and alter mode to reflect the fact the
20125 check constraint is in alter_mode as this information is not stored
20126 parsistently.
20127
20128 @param new_table New table definition.
20129 @param alter_info Alter_info object containing list of list of
20130 check constraint spec for table being
20131 altered.
20132 */
20133 34429 static void set_check_constraints_alter_mode(dd::Table *new_table,
20134 Alter_info *alter_info) {
20135
6/10
✓ Branch 0 taken 34429 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 34429 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 34429 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 641 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 641 times.
✓ Branch 9 taken 34429 times.
35070 for (dd::Check_constraint *cc : *new_table->check_constraints()) {
20136
3/4
✓ Branch 0 taken 641 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 636 times.
✓ Branch 3 taken 5 times.
641 if (cc->is_alter_mode()) continue;
20137 5 for (Sql_check_constraint_spec *cc_spec :
20138
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 5 times.
10 alter_info->check_constraint_spec_list) {
20139
3/6
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
5 if (!my_strcasecmp(system_charset_info, cc->name().c_str(),
20140 cc_spec->alias_name.str)) {
20141
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 cc->set_name(cc_spec->name.str);
20142
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 cc->set_alias_name(cc_spec->alias_name.str);
20143
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 cc->set_alter_mode(true);
20144 }
20145 }
20146 }
20147 34429 }
20148
20149 /**
20150 Reset alter mode of check constraints.
20151
20152 Method updates only dd::Table object. It is not stored or updated to
20153 data-dictionary in this method.
20154
20155 @param new_table New table definition.
20156 */
20157 75172 static void reset_check_constraints_alter_mode(dd::Table *new_table) {
20158
6/10
✓ Branch 0 taken 75172 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 75172 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 75172 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 946 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 946 times.
✓ Branch 9 taken 75172 times.
76118 for (dd::Check_constraint *cc : *new_table->check_constraints()) {
20159
2/4
✓ Branch 0 taken 946 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 946 times.
946 assert(cc->is_alter_mode());
20160
1/2
✓ Branch 0 taken 946 times.
✗ Branch 1 not taken.
946 cc->set_alter_mode(false);
20161 }
20162 75172 }
20163
20164 /**
20165 Make old table definition's check constraint use temporary names. This is
20166 needed to avoid problems with duplicate check constraint names while we
20167 have two definitions of the same table.
20168 Method updates only dd::Table object. It is not stored or updated to
20169 data-dictionary in this method.
20170
20171 @param thd Thread context.
20172 @param old_table_db Database of old table.
20173 @param old_table Old table definition.
20174
20175 @returns false - Success, true - Failure.
20176 */
20177 18334 static bool adjust_check_constraint_names_for_old_table_version(
20178 THD *thd, const char *old_table_db, dd::Table *old_table) {
20179
1/2
✓ Branch 0 taken 18334 times.
✗ Branch 1 not taken.
18334 MDL_request_list mdl_requests;
20180
6/10
✓ Branch 0 taken 18334 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18334 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18334 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 562 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 562 times.
✓ Branch 9 taken 18334 times.
18896 for (dd::Check_constraint *cc : *old_table->check_constraints()) {
20181 562 const int prefix_len = 4; // #cc_
20182 562 const int id_len = 20;
20183 char temp_cc_name[prefix_len + id_len + 1];
20184 1124 snprintf(temp_cc_name, sizeof(temp_cc_name), "#cc_%llu",
20185
1/2
✓ Branch 0 taken 562 times.
✗ Branch 1 not taken.
562 (ulonglong)cc->id());
20186
20187 /*
20188 Acquire lock on temporary names before updating data-dictionary just in
20189 case somebody tries to create check constraints with same name.
20190 */
20191
2/4
✓ Branch 0 taken 562 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 562 times.
562 if (push_check_constraint_mdl_request_to_list(thd, old_table_db,
20192 temp_cc_name, mdl_requests))
20193 return true;
20194
20195 // Set adjusted name.
20196
2/4
✓ Branch 0 taken 562 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 562 times.
✗ Branch 3 not taken.
562 cc->set_name(temp_cc_name);
20197 }
20198
20199
2/4
✓ Branch 0 taken 18334 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18334 times.
18334 if (thd->mdl_context.acquire_locks(&mdl_requests,
20200 thd->variables.lock_wait_timeout))
20201 return true;
20202
20203 18334 return false;
20204 }
20205
20206 /**
20207 Helper method to check if any check constraints (re-)evaluation is required.
20208 If any check constraint re-evaluation is required then in-place alter is not
20209 possible as it is done in the SQL-layer. This method is called by
20210 is_inplace_alter_impossible() to check inplace alter is possible.
20211
20212 Check constraint (re-)evaluation is required when
20213 1) New check constraint is added in ENFORCED state.
20214 2) Any existing check constraint is ENFORCED.
20215 3) Type of column used by any enforced check constraint is changed.
20216 4) check constraints expression depends on DEFAULT function on a column and
20217 default is changed as part of alter operation.
20218
20219 @param alter_info Data related to detected changes.
20220
20221 @retval true Check constraint (re-)evaluation required.
20222 @retval false Otherwise.
20223 */
20224 86984 static bool is_any_check_constraints_evaluation_required(
20225 const Alter_info *alter_info) {
20226 /*
20227 Check if any check constraint is added in enforced state or state of any
20228 check is is changed to ENFORCED.
20229 */
20230
2/2
✓ Branch 0 taken 113 times.
✓ Branch 1 taken 86871 times.
86984 if (alter_info->flags & Alter_info::ENFORCE_CHECK_CONSTRAINT) return true;
20231
20232
2/2
✓ Branch 0 taken 724 times.
✓ Branch 1 taken 86860 times.
87584 for (auto &cc_spec : alter_info->check_constraint_spec_list) {
20233
2/2
✓ Branch 0 taken 610 times.
✓ Branch 1 taken 114 times.
724 if (!cc_spec->is_enforced) continue;
20234
20235 /*
20236 if column is modified then check if type is changed or if default value is
20237 changed. Check constraint re-evaluation is required in this case.
20238 */
20239
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 68 times.
114 if (alter_info->flags & Alter_info::ALTER_CHANGE_COLUMN) {
20240
5/8
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 167 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 131 times.
✓ Branch 7 taken 36 times.
167 for (const Create_field &fld : alter_info->create_list) {
20241 // Get fields used by check constraint.
20242
1/2
✓ Branch 0 taken 131 times.
✗ Branch 1 not taken.
131 mem_root_deque<Item_field *> fields(current_thd->mem_root);
20243
1/2
✓ Branch 0 taken 131 times.
✗ Branch 1 not taken.
131 cc_spec->check_expr->walk(&Item::collect_item_field_processor,
20244 enum_walk::POSTFIX, (uchar *)&fields);
20245
7/12
✓ Branch 0 taken 131 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 131 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 254 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 246 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 377 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 254 times.
✓ Branch 11 taken 123 times.
377 for (Item_field *itm_fld : fields) {
20246
6/8
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 252 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 252 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 252 times.
254 if (itm_fld->type() != Item::FIELD_ITEM || itm_fld->field == nullptr)
20247 2 continue;
20248
20249 // Check if data type is changed.
20250
1/2
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
252 if (!my_strcasecmp(system_charset_info, itm_fld->field_name,
20251
4/4
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 170 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 244 times.
334 fld.field_name) &&
20252
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 74 times.
82 (itm_fld->data_type() != fld.sql_type))
20253 8 return true;
20254 }
20255
20256 /*
20257 If column is modified then default might have changed. Check if
20258 check constraint uses default function.
20259 */
20260
4/4
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 85 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 121 times.
161 if (fld.change &&
20261
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 36 times.
38 cc_spec->check_expr->walk(
20262 &Item::check_gcol_depend_default_processor, enum_walk::POSTFIX,
20263
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 reinterpret_cast<uchar *>(const_cast<char *>(fld.change))))
20264 2 return true;
20265
2/2
✓ Branch 0 taken 121 times.
✓ Branch 1 taken 10 times.
131 }
20266 }
20267
20268 /*
20269 If column is altered to drop or set default then check any check
20270 constraint using the default function. Re-evaluation of check constraint
20271 is required in this case.
20272 */
20273
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 102 times.
104 if (alter_info->flags & Alter_info::ALTER_CHANGE_COLUMN_DEFAULT) {
20274
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (auto *alter : alter_info->alter_list) {
20275
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 if (alter->change_type() == Alter_column::Type::SET_DEFAULT ||
20276 alter->change_type() == Alter_column::Type::DROP_DEFAULT) {
20277
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (cc_spec->check_expr->walk(
20278 &Item::check_gcol_depend_default_processor,
20279 enum_walk::POSTFIX,
20280 2 reinterpret_cast<uchar *>(const_cast<char *>(alter->name))))
20281 1 return true;
20282 }
20283 }
20284 }
20285 }
20286
20287 86860 return false;
20288 }
20289
20290 2193 bool lock_check_constraint_names_for_rename(THD *thd, const char *db,
20291 const char *table_name,
20292 const dd::Table *table_def,
20293 const char *target_db,
20294 const char *target_table_name) {
20295
1/2
✓ Branch 0 taken 2193 times.
✗ Branch 1 not taken.
2193 DBUG_TRACE;
20296
1/2
✓ Branch 0 taken 2193 times.
✗ Branch 1 not taken.
2193 MDL_request_list mdl_requests;
20297 2193 size_t table_name_len = strlen(table_name);
20298
20299 // Push lock requests for the check constraints defined on db.table_name.
20300
6/10
✓ Branch 0 taken 2193 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2193 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2193 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 25 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 25 times.
✓ Branch 9 taken 2193 times.
2218 for (auto &cc : table_def->check_constraints()) {
20301
3/6
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 25 times.
25 if (push_check_constraint_mdl_request_to_list(thd, db, cc->name().c_str(),
20302 mdl_requests))
20303 return true;
20304 }
20305
20306 // Push lock request for the check constraints in target table.
20307
6/10
✓ Branch 0 taken 2193 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2193 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2193 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 25 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 25 times.
✓ Branch 9 taken 2193 times.
2218 for (auto &cc : table_def->check_constraints()) {
20308
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 const char *cc_name = cc->name().c_str();
20309 /*
20310 If check constraint name is a generated name in the source table then
20311 generate name with the target table to create mdl_request with it.
20312 */
20313
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 bool is_generated_name = dd::is_generated_check_constraint_name(
20314
2/4
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
25 table_name, table_name_len, cc->name().c_str(), cc->name().length());
20315
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 7 times.
25 if (is_generated_name) {
20316 char *end;
20317 uint number =
20318
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 my_strtoull(cc->name().c_str() + table_name_len +
20319 18 sizeof(dd::CHECK_CONSTRAINT_NAME_SUBSTR) - 1,
20320 18 &end, 10);
20321 LEX_STRING name;
20322
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (generate_check_constraint_name(thd, target_table_name, number, name,
20323 true))
20324 return true;
20325 18 cc_name = name.str;
20326 }
20327
20328 /*
20329 If check constraint name is generated or table moved different database
20330 then create mdl_request with target_db.cc_name.
20331 */
20332 32 if ((is_generated_name ||
20333
6/8
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 25 times.
44 my_strcasecmp(table_alias_charset, db, target_db)) &&
20334
2/4
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
19 push_check_constraint_mdl_request_to_list(thd, target_db, cc_name,
20335 mdl_requests))
20336 return true;
20337 }
20338
20339 // Acquire locks on all the collected check constraint names.
20340
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2179 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2193 times.
2207 if (!mdl_requests.is_empty() &&
20341
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
14 thd->mdl_context.acquire_locks(&mdl_requests,
20342 thd->variables.lock_wait_timeout))
20343 return true;
20344
20345
2/4
✓ Branch 0 taken 2193 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2193 times.
✗ Branch 3 not taken.
2193 DEBUG_SYNC(thd, "after_acquiring_lock_on_check_constraints_for_rename");
20346
20347 2193 return false;
20348 2193 }
20349
20350 151509 bool lock_check_constraint_names(THD *thd, TABLE_LIST *tables) {
20351
1/2
✓ Branch 0 taken 151509 times.
✗ Branch 1 not taken.
151509 DBUG_TRACE;
20352 151509 MEM_ROOT mdl_reqs_root(key_memory_rm_db_mdl_reqs_root, MEM_ROOT_BLOCK_SIZE);
20353
1/2
✓ Branch 0 taken 151509 times.
✗ Branch 1 not taken.
151509 MDL_request_list mdl_requests;
20354
20355
2/2
✓ Branch 0 taken 188936 times.
✓ Branch 1 taken 151509 times.
340445 for (TABLE_LIST *table = tables; table != nullptr;
20356 188936 table = table->next_local) {
20357
6/6
✓ Branch 0 taken 177834 times.
✓ Branch 1 taken 11102 times.
✓ Branch 2 taken 43041 times.
✓ Branch 3 taken 134793 times.
✓ Branch 4 taken 43041 times.
✓ Branch 5 taken 145895 times.
201062 if (table->open_type != OT_BASE_ONLY && is_temporary_table(table)) continue;
20358
20359
1/2
✓ Branch 0 taken 145895 times.
✗ Branch 1 not taken.
145895 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
20360
20361 145895 const dd::Abstract_table *abstract_table_def = nullptr;
20362
4/8
✓ Branch 0 taken 145895 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 145895 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 145895 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 145895 times.
145895 if (thd->dd_client()->acquire(table->db, table->table_name,
20363 &abstract_table_def))
20364 return true;
20365
20366
4/4
✓ Branch 0 taken 134636 times.
✓ Branch 1 taken 11259 times.
✓ Branch 2 taken 12126 times.
✓ Branch 3 taken 133769 times.
280531 if (abstract_table_def == nullptr ||
20367
3/4
✓ Branch 0 taken 134636 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 867 times.
✓ Branch 3 taken 133769 times.
134636 abstract_table_def->type() != dd::enum_table_type::BASE_TABLE)
20368 12126 continue;
20369
20370 const dd::Table *table_def =
20371
1/2
✓ Branch 0 taken 133769 times.
✗ Branch 1 not taken.
133769 dynamic_cast<const dd::Table *>(abstract_table_def);
20372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 133769 times.
133769 assert(table_def != nullptr);
20373
20374 /*
20375 Ensure that we don't hold memory used by MDL_requests after locks
20376 have been acquired. This reduces memory usage in cases when we have
20377 DROP DATABASE that needs to drop lots of different objects.
20378 */
20379 133769 MEM_ROOT *save_thd_mem_root = thd->mem_root;
20380 auto restore_thd_mem_root =
20381
1/2
✓ Branch 0 taken 133769 times.
✗ Branch 1 not taken.
133769 create_scope_guard([&]() { thd->mem_root = save_thd_mem_root; });
20382 133769 thd->mem_root = &mdl_reqs_root;
20383
20384
6/10
✓ Branch 0 taken 133769 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 133769 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 133769 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 646 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 646 times.
✓ Branch 9 taken 133769 times.
134415 for (auto &cc : table_def->check_constraints()) {
20385
2/4
✓ Branch 0 taken 646 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 646 times.
646 if (push_check_constraint_mdl_request_to_list(
20386
1/2
✓ Branch 0 taken 646 times.
✗ Branch 1 not taken.
646 thd, table->db, cc->name().c_str(), mdl_requests))
20387 return false;
20388 }
20389
3/5
✓ Branch 0 taken 133769 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 133769 times.
✓ Branch 3 taken 12126 times.
✗ Branch 4 not taken.
145895 }
20390
20391 // Acquire MDL lock on all the check constraint names.
20392
3/4
✓ Branch 0 taken 371 times.
✓ Branch 1 taken 151138 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 151509 times.
151880 if (!mdl_requests.is_empty() &&
20393
2/4
✓ Branch 0 taken 371 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 371 times.
371 thd->mdl_context.acquire_locks(&mdl_requests,
20394 thd->variables.lock_wait_timeout))
20395 return true;
20396
20397 151509 return false;
20398 151509 }
20399